2017-07-14 48 views
2

讓我們asume接口C#是通用型與普通型約束

interface IOwnedBy<T> where T : IOwner 
{ 
    T Owner { get; } 
} 

interface IOwner 
{ 
    public int Id { get; } 
} 

某處在我的代碼,我想做到以下幾點:

if (obj is OwnedBy<IOwner>) 
{ 
    DoSomethingWith(obj.Owner.Id); 
} 

基本上,我想檢查obj是否是任何OwnedBy實現。由於IOwner是任何泛型參數的類型約束,所以我認爲這是可行的。但是這種情況從未得到滿足。

任何方式沒有使用很多反射?

回答

7

更改該界面在T被協變:

interface IOwnedBy<out T> where T : IOwner 
{ 
    T Owner { get; } 
} 

obj is OwnedBy<IOwner>失敗,因爲編譯器無法知道它安全; IOwnedBy被聲明爲不變量。如果你明確地告訴編譯器它是協變的,那麼知道轉換是安全的,它將工作。

爲什麼它在不變的界面中不安全?考慮以下幾點:

interface IOwnedBy<T> where T : IOwner 
{ 
    T Owner { get; } 
    void SetOwner(T Owner); 
} 

class Person: IOwner { } 
class Cat: IOwner { } 

Cat tom = ... 

IOwnedBy<Person> owned = ... 
var nope = owned as IOwnedBy<IOwner>; 
nope.SetOwner(tom); //Ouch! Just set a cat as an owner of a IOwnedBy<Person> 
+1

我只是寫了一個確切的答案,並且正在研究一個現場示例 - 如果需要,您可以將其包含在內。沒有重複你的答案。 http://rextester.com/BRT23576 – Jamiec

+0

謝謝你們,很好的解釋和例子! – mbue