{"id":368,"date":"2014-09-16T12:48:59","date_gmt":"2014-09-16T12:48:59","guid":{"rendered":"http:\/\/mairwa.com\/wordpress\/?p=368"},"modified":"2014-09-16T12:48:59","modified_gmt":"2014-09-16T12:48:59","slug":"covariance-and-contravariance-in-generics","status":"publish","type":"post","link":"http:\/\/mairwa.com\/wordpress\/?p=368","title":{"rendered":"Covariance and Contravariance in Generics"},"content":{"rendered":"<p>In probability theory and statistics, <b>covariance<\/b> is a measure of how much two random variables change together. If the greater values of one variable mainly correspond with the greater values of the other variable, and the same holds for the smaller values, i.e., the variables tend to show similar behavior, the covariance is positive.In the opposite case, when the greater values of one variable mainly correspond to the smaller values of the other, i.e., the variables tend to show opposite behavior, the covariance is negative. The sign of the covariance therefore shows the tendency in the linear relationship between the variables.<\/p>\n<p>CLR team might have found my assumption quite viable and it got shape in .NET 4.0 as <strong>\u201cCovariance and Contravariance in Generics\u201d.<\/strong><\/p>\n<p><b>Variance<\/b> is a special case of the covariance when the two variables are identical<\/p>\n<p><b>Covariance<\/b><b> and <\/b><b>contravariance<\/b> of generic type parameters enable to use constructed generic types whose type arguments are more derived (covariance) or less derived (contravariance) than a target constructed type.<\/p>\n<p><strong>In general, a covariant type parameter can be used as the return type of a generic delegate\/interface, and contravariant type parameters can be used as input parameter types.<\/strong><\/p>\n<p><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/9eekhta0%28v=vs.110%29.aspx\">IEnumerable&lt;T&gt;<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/78dfe2yb%28v=vs.110%29.aspx\">IEnumerator&lt;T&gt;<\/a>&#8212;&#8211;<b> <\/b><b>Covariance<\/b><\/p>\n<p><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/tfakywbh%28v=vs.110%29.aspx\">Comparison&lt;T&gt;<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/018hxwa8%28v=vs.110%29.aspx\">Action&lt;T&gt;<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/8ehhxeaf%28v=vs.110%29.aspx\">IComparer&lt;T&gt;<\/a>&#8212;<b> <\/b><b>contravariance<\/b><\/p>\n<p><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb549151%28v=vs.110%29.aspx\">Func&lt;T, TResult&gt;<\/a>, <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/kt456a2y%28v=vs.110%29.aspx\">Converter&lt;TInput, TOutput&gt;<\/a>&#8212; Encapsulates a method that has one parameter and returns a value of the type specified by the TResult parameter.it is <b>Covariance and <\/b><b>contravariance support.<\/b><\/p>\n<pre>Func&lt;string, string&gt; convertMethod = UppercaseString;(it<\/pre>\n<pre>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0string name = \"Dakota\";<\/pre>\n<pre>\u00a0\u00a0\u00a0\u00a0\u00a0 \/\/ Use delegate instance to call UppercaseString method<\/pre>\n<pre>\u00a0\u00a0\u00a0\u00a0\u00a0 Console.WriteLine(convertMethod(name));<\/pre>\n<p>&nbsp;<\/p>\n<pre>IEnumerable&lt; BaseVO &gt; lstBaseVO = new List&lt; FlightVO &gt;();The above statement is valid because, in .NET 4.0, <code>List&lt;T&gt; : IEnumerable&lt;out T&gt;<\/code> <strong>where type \u2018T\u2019 is marked as covariant.<\/strong><\/pre>\n<ul>\n<li>A covariant type parameter is marked with the out keyword. we cannot use a covariant type parameter as a generic type constraint for interface methods. E.g., T Display&lt;out T&gt;(); is an invalid statement.<\/li>\n<li>A contravariant type parameter is marked with the in keyword. we can use a contravariant type parameter as a generic type constraint for an interface method.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Generic delegates enable type-safe callbacks without the need to create multiple delegate classes<\/p>\n<table border=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td>where T : class<\/td>\n<td>The type argument must be a reference type; this applies also to any class, interface, delegate, or array type.<\/td>\n<\/tr>\n<tr>\n<td>where T : new()<\/td>\n<td>The type argument must have a public parameterless constructor. When used together with other constraints, the new() constraint must be specified last.<\/td>\n<\/tr>\n<tr>\n<td>where T : &lt;base class name&gt;<\/td>\n<td>The type argument must be or derive from the specified base class.<\/td>\n<\/tr>\n<tr>\n<td>where T : &lt;interface name&gt;<\/td>\n<td>The type argument must be or implement the specified interface. Multiple interface constraints can be specified. The constraining interface can also be generic.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<pre>public\u00a0static\u00a0void OpTest&lt;T&gt;(T s, T t) where T : class<\/pre>\n<pre>{<\/pre>\n<pre>\u00a0\u00a0\u00a0 System.Console.WriteLine(s == t);<\/pre>\n<pre>}<\/pre>\n<pre>static\u00a0void Main()<\/pre>\n<pre>{<\/pre>\n<pre>\u00a0\u00a0\u00a0 string s1 = \"target\";<\/pre>\n<pre>\u00a0\u00a0\u00a0 System.Text.StringBuilder sb = new System.Text.StringBuilder(\"target\");<\/pre>\n<pre>\u00a0\u00a0\u00a0 string s2 = sb.ToString();<\/pre>\n<pre>\u00a0\u00a0\u00a0 OpTest&lt;string&gt;(s1, s2);<\/pre>\n<pre>}<\/pre>\n<p>For a generic class Node&lt;T&gt;, client code can reference the class either by specifying a type argument, to create a closed constructed type (Node&lt;int&gt;). Alternatively, it can leave the type parameter unspecified, for example when you specify a generic base class, to create an open constructed type (Node&lt;T&gt;). Generic classes can inherit from concrete<b>, closed constructed<\/b>, or <b>open constructed<\/b> base classes:<\/p>\n<pre>class BaseNode { }<\/pre>\n<pre>class BaseNodeGeneric&lt;T&gt; { }<\/pre>\n<pre>\/\/An <em>unbound<\/em> type has no type arguments specified(collection class)<\/pre>\n<pre><\/pre>\n<pre>\/\/ concrete type<\/pre>\n<pre>class NodeConcrete&lt;T&gt; : BaseNode { }<\/pre>\n<pre><\/pre>\n<pre>\/\/closed constructed type<\/pre>\n<pre>class NodeClosed&lt;T&gt; : BaseNodeGeneric&lt;int&gt; { }<\/pre>\n<pre><\/pre>\n<pre>\/\/open constructed type<\/pre>\n<pre>class NodeOpen&lt;T&gt; : BaseNodeGeneric&lt;T&gt; { }<\/pre>\n<pre><\/pre>\n<h1>Generic Delegates<\/h1>\n<pre>A delegate can define its own type parameters. Code that references the generic delegate can specify the type argument to create a closed constructed type, just like when instantiating a generic class or calling a generic method.<\/pre>\n<pre>public\u00a0delegate\u00a0void Del&lt;T&gt;(T item);<\/pre>\n<pre>public\u00a0static\u00a0void Notify(int i) { }<\/pre>\n<pre><\/pre>\n<pre>Del&lt;int&gt; m1 = new Del&lt;int&gt;(Notify);\n\n\n<\/pre>\n<h3>Contravariance<\/h3>\n<p><em>Contravariance<\/em> works the other way than <em>covariance<\/em>. Let&#8217;s say we have a method that creates some cats and compares them using a provided <code>IComparer&lt;Cat&gt;<\/code> object. In a more realistic example, the method might, for example, sort the cats:<\/p>\n<pre>void CompareCats(IComparer&lt;Cat&gt; comparer) {\n  var cat1 = new Cat(\"Otto\");\n  var cat2 = new Cat(\"Troublemaker\");\n  if (comparer.Compare(cat2, cat1) &gt; 0) \n    Console.WriteLine(\"Troublemaker wins!\");\n}<\/pre>\n<p>The <code>comparer<\/code> object takes cats as arguments, but it never returns a cat as the result. You could say that it is a write-only in the way in which it uses the generic type parameter. Now, thanks to <em>contravariance<\/em>, we can create a comparer that can compare animals and use it as an argument to <code>CompareCats<\/code>:<\/p>\n<pre>IComparator&lt;Animal&gt; compareAnimals = new AnimalSizeComparator();\nCompareCats(compareAnimals);<\/pre>\n<p>The compiler accepts this code because the <code>IComparer<\/code> interface is <em>contravariant<\/em> and its generic type parameter is marked with the <code>in<\/code> annotation. When you run the program, it also makes sense. The <code>compareAnimals<\/code> object that we created knows how to compare animals and so it can certainly also compare two cats. A problem would be if we could read a <code>Cat<\/code> from <code>IComparer&lt;Cat&gt;<\/code> (because we couldn&#8217;t get <code>Cat<\/code> from <code>IComparer&lt;Animal&gt;<\/code>!), but that is not possible, because <code>IComparer<\/code> is write-only.<\/p>\n","protected":false},"excerpt":{"rendered":"<p class=\"excerpt\">In probability theory and statistics, covariance is a measure of how much two random variables change together. If the greater values of one variable mainly correspond with the greater values of the other variable, and the same holds for the smaller values, i.e., the variables tend to show similar behavior, the covariance is positive.In the opposite case, when the greater&hellip; <a href=\"http:\/\/mairwa.com\/wordpress\/?p=368\">Read more &rarr;<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-368","post","type-post","status-publish","format-standard","hentry","category-c-vb","xfolkentry"],"_links":{"self":[{"href":"http:\/\/mairwa.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/368","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/mairwa.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/mairwa.com\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/mairwa.com\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/mairwa.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=368"}],"version-history":[{"count":0,"href":"http:\/\/mairwa.com\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/368\/revisions"}],"wp:attachment":[{"href":"http:\/\/mairwa.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=368"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/mairwa.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=368"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/mairwa.com\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=368"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}