I had a full wtf moment when working with covariant interfaces.
Consider the following:
class Fruit { }
class Apple : Fruit { }
interface IBasket<out T> { }
class FruitBasket : IBasket<Fruit> { }
class AppleBasket : IBasket<Apple> { }
Note:
AppleBasket not inherited from FruitBasket .IBasket covariant .
Later in the script you write:
FruitBasket fruitBasket = new FruitBasket();
AppleBasket appleBasket = new AppleBasket();
Log(fruitBasket is IBasket<Fruit>);
Log(appleBasket is IBasket<Apple>);
... and, as expected, the conclusion:
true
true
HOWEVER , consider the following code:
AppleBasket appleBasket = new AppleBasket();
Log(appleBasket is IBasket<Fruit>);
You expect him to output true, right? Well, you're wrong - at least with my compiler:
false
It's weird, but maybe it does an implicit conversion , similar to converting intto long. intis not a view long, but an int can be assigned to a long one implicitly.
HOWEVER, :
IBasket<Fruit> basket = new AppleBasket();
Log(basket is IBasket<Fruit>);
- - , AppleBasket IBasket<Fruit>. , .
basket - IBasket<Fruit> - IBasket<Fruit>... , . ?
, is, ! :
false
... IBasket<Fruit> fruit IBasket<Fruit>... Huh?
... :
IBasket<Fruit> FruitBasket { get { ... } }
-, null, IBasket<Fruit>.
FURTHER, ReSharper , appleBasket is IBasket<Fruit> , AppleBasket appleBasket != null... ReSharper ?
, ? # (Unity 5.3.1p4 - It Unity Mono, .NET 2.0), ?