Covariance C# with Example



Covariance C# with Example

When is an IEnumerable a subtype of a different IEnumerable? When T is a subtype of T1. IEnumerable is 
covariant in its T parameter, which means that IEnumerable's subtype relationship goes in the same direction as T's. 
class Animal { /* ... */ } 
class Dog : Animal { /* ... */ } 
IEnumerable dogs = Enumerable.Empty(); 
IEnumerable animals = dogs; // IEnumerable is a subtype of IEnumerable 
// dogs = animals; // Compilation error - IEnumerable is not a subtype of IEnumerable 
An instance of a covariant generic type with a given type parameter is implicitly convertible to the same generic 
type with a less derived type parameter. 
This relationship holds because IEnumerable produces Ts but doesn't consume them. An object that produces Dogs 
can be used as if it produces Animals. 
Covariant type parameters are declared using the out keyword, because the parameter must be used only as an 
output. 
interface IEnumerable { /* ... */ } 
A type parameter declared as covariant may not appear as an input. 
interface Bad 
{ 
void SetT(T t); // type error 
} 
Here's a complete example: 
using NUnit.Framework; 
namespace ToyStore 
{ 
enum Taste { Bitter, Sweet }; 
 

interface IWidget 
{ 
int Weight { get; } 
} 
interface IFactory 
where TWidget : IWidget 
{ 
TWidget Create(); 
} 
class Toy : IWidget 
{ 
public int Weight { get; set; } 
public Taste Taste { get; set; } 
} 
class ToyFactory : IFactory 
{ 
public const int StandardWeight = 100; 
public const Taste StandardTaste = Taste.Sweet; 
public Toy Create() { return new Toy { Weight = StandardWeight, Taste = StandardTaste }; } 
} 
[TestFixture] 
public class GivenAToyFactory 
{ 
[Test] 
public static void WhenUsingToyFactoryToMakeWidgets() 
{ 
var toyFactory = new ToyFactory(); 
//// Without out keyword, note the verbose explicit cast: 
//  IFactory  rustBeltFactory  =  (IFactory)toyFactory; 
// covariance: concrete being assigned to abstract (shiny and new) 
IFactory widgetFactory = toyFactory; 
IWidget anotherToy = widgetFactory.Create(); 
Assert.That(anotherToy.Weight, Is.EqualTo(ToyFactory.StandardWeight)); // abstract 
contract 
Assert.That(((Toy)anotherToy).Taste, Is.EqualTo(ToyFactory.StandardTaste)); // concrete 
contract 
} 
} 
} 

0 Comment's

Comment Form