<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx</link><description>UPDATE: Andrew Kennedy, author of the paper I reference below, was good enough to point out some corrections and omissions, which I have addressed. Thanks Andrew! As I've discussed at length in this space, we are considering adding covariance and contravariance</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8466645</link><pubDate>Wed, 07 May 2008 22:08:23 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8466645</guid><dc:creator>Frank Quednau</dc:creator><description>&lt;p&gt;&amp;quot;expression is too complex to compile&amp;quot; is actually what my brain said, too. Indeed, the whole subject is fascinating and your posts on the issue are on the &amp;quot;toread&amp;quot; list.&lt;/p&gt;
&lt;p&gt;For now, I just can't manage to assign null to a struct - a feat that Nullable&amp;lt;T&amp;gt; seems to be perfectly capable of. How can I implicitly convert a null to a struct? the closest I get gives me CS0553...sorry I ranted here, but it was bugging me and your post right from the compiler front hit me on my Feed :)&lt;/p&gt;
&lt;p&gt;Thanks for your valuable and brain-crunching posts!&lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8466889</link><pubDate>Wed, 07 May 2008 23:05:59 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8466889</guid><dc:creator>Eric Lippert</dc:creator><description>&lt;p&gt;Nullable&amp;lt;T&amp;gt; does not assign a null to a struct. Nullable&amp;lt;T&amp;gt; is nothing more nor less than simply a struct something like:&lt;/p&gt;
&lt;p&gt;struct Nullable&amp;lt;T&amp;gt; where T : struct&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp;readonly T t;&lt;/p&gt;
&lt;p&gt; &amp;nbsp;readonly bool hasValue;&lt;/p&gt;
&lt;p&gt; &amp;nbsp;... constructors, accessors, and so on&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;That's all folks. The rest is just compiler and runtime magic. &amp;nbsp;The compiler turns &amp;quot;if (n == null)&amp;quot; into &amp;quot;if (n.HasValue == false)&amp;quot;, turns &amp;quot;int n = null&amp;quot; into &amp;quot;n = new Nullable&amp;lt;int&amp;gt;();&amp;quot;, etc. &lt;/p&gt;
&lt;p&gt;Perhaps what you want to do is not &amp;quot;convert a null to a struct&amp;quot; but rather &amp;quot;get the default value for a struct&amp;quot;? &amp;nbsp;In that case you can just say:&lt;/p&gt;
&lt;p&gt;T t = default(T);&lt;/p&gt;
&lt;p&gt;If T is numeric, default(T) is zero. &amp;nbsp;If T is a reference type, default(T) is null. &amp;nbsp;bool -- false. &amp;nbsp;Nullable type -- nullable type with hasValue=false. struct -- struct with all its fields set to THEIR default types.&lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8467187</link><pubDate>Thu, 08 May 2008 00:13:29 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8467187</guid><dc:creator>David Nelson</dc:creator><description>&lt;p&gt;My head is about to spin clean off my neck. &amp;quot;expression is too complex to compile&amp;quot; is a dramatic understatement.&lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8468868</link><pubDate>Thu, 08 May 2008 07:39:58 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8468868</guid><dc:creator>Digitake</dc:creator><description>&lt;p&gt;I think Church shows that this kind of the problem,i.e. to decide which expressions are equivalent, is an unsolvable problems.&lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8470694</link><pubDate>Thu, 08 May 2008 13:06:26 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8470694</guid><dc:creator>Frank Quednau</dc:creator><description>&lt;p&gt;Hi Eric,&lt;/p&gt;
&lt;p&gt;thank you for your answers. I think I expressed myself too bland yesterday, I was more or less aware of the issues...&lt;/p&gt;
&lt;p&gt;I was looking for a way as a .NET developer to get an analogous code statement to compile (In the wake of me having a lot of fun with the implicit operator). Anyway, most importantly for me was the info that the compiler does some magic, so there is no way to get the effect via developer-made .NET code. That's fine by me, but good to know.&lt;/p&gt;
&lt;p&gt;Cheers and thanks :)&lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8480471</link><pubDate>Fri, 09 May 2008 18:04:49 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8480471</guid><dc:creator>Joren Vermijs</dc:creator><description>&lt;p&gt;Is it not so that since double and string have no hierarchical relation, co- and contravariance are not relevant for determining A&amp;lt;double&amp;gt; -&amp;gt; B&amp;lt;string&amp;gt;, whatever A and B may be? Covariance preserves ordering, contravariance reverses ordering, but neither _creates_ ordering, as far as I see.&lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8486504</link><pubDate>Sun, 11 May 2008 12:25:16 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8486504</guid><dc:creator>configurator</dc:creator><description>&lt;p&gt;Joren, it is in fact so, but that is not exactly the question at hand.&lt;/p&gt;
&lt;p&gt;The question is not whether or not the cast is valid. The question is how to write the compiler to know that.&lt;/p&gt;
&lt;p&gt;On the same note, think of as example for the halting problem (even though it is not equivalent, as Eric said):&lt;/p&gt;
&lt;p&gt;write a program that can tell if the following method stops or not:&lt;/p&gt;
&lt;p&gt;int thing(int x) { return thing(x + 1); }&lt;/p&gt;
&lt;p&gt;Surely, both you and I can see that this method will never stop (disregarding the overflow exception). But for a computer program, it would not be that obvious.&lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8487266</link><pubDate>Sun, 11 May 2008 16:47:52 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8487266</guid><dc:creator>Joren Vermijs</dc:creator><description>&lt;p&gt;Re: The question is how to write the compiler to know whether or not the cast is valid.&lt;/p&gt;
&lt;p&gt;Yes, I understand that. Eric said the problem is not solvable in general, so returning the error 'too complex to compile' is a fine approach. &lt;/p&gt;
&lt;p&gt;But I thought: is it not at least possible to write a compiler that can follow the reasoning from the string-double relation (or other simple relations) to the interface relation, in stead of only trying to reduce the generic interface relation to a simple relation (which, as my previous post implied, can fail while the other method works)?&lt;/p&gt;
&lt;p&gt;It seems that trying the problem A&amp;lt;X&amp;gt; -&amp;gt; B&amp;lt;Y&amp;gt; from both sides (both from the relation between X and Y, and the relation between A and B) will lead to more classes of cases that the compiler can handle without giving up.&lt;/p&gt;
&lt;p&gt;Of course the question remains whether anything whose validity can't be ascertained from the relation between A and B alone will ever be practically useful. I'd say 'no' is most likely, but I've hardly investigated the problem any further.&lt;/p&gt;
</description></item><item><title>VCS Team Links for May 22, 2008</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8533332</link><pubDate>Thu, 22 May 2008 22:12:36 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8533332</guid><dc:creator>Charlie Calvert's Community Blog</dc:creator><description>&lt;p&gt;Rather than place the links to the most recent C# team content directly in Community Convergence , I&lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8623041</link><pubDate>Thu, 19 Jun 2008 23:44:31 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8623041</guid><dc:creator>orangy</dc:creator><description>&lt;p&gt;I wonder if some future CSC could allow implicit interface implementation in variant way?&lt;/p&gt;
&lt;p&gt;Like this:&lt;/p&gt;
&lt;p&gt;class MyPOD : IClonable&lt;/p&gt;
&lt;p&gt;{&lt;/p&gt;
&lt;p&gt; &amp;nbsp;public MyPOD Clone() { ... } // this could implicitly implement IClonable.Clone &lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;Eric, can such variance be specified on IClonable interface? &lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8623066</link><pubDate>Thu, 19 Jun 2008 23:50:59 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8623066</guid><dc:creator>Eric Lippert</dc:creator><description>&lt;p&gt;That kind of variance is called &amp;quot;return type covariance&amp;quot;. As I mentioned early on in this series, (a) this series is not about that kind of variance, and (b) we have no plans to implement that kind of variance in C#. &amp;nbsp;&lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8685612</link><pubDate>Fri, 04 Jul 2008 00:07:59 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8685612</guid><dc:creator>Konstantin Triger</dc:creator><description>&lt;p&gt;Hello Eric,&lt;/p&gt;
&lt;p&gt;After my last re-reading of your co[ntra]variance series, I believe I came to a new point.&lt;/p&gt;
&lt;p&gt;After all there are only 3 possibilites:&lt;/p&gt;
&lt;p&gt;1. Clear covariance (IEnumerator&amp;lt;T&amp;gt;).&lt;/p&gt;
&lt;p&gt;2. Clear contravariance (IComparer&amp;lt;T&amp;gt;).&lt;/p&gt;
&lt;p&gt;3. Undecidable (IList&amp;lt;T&amp;gt;).&lt;/p&gt;
&lt;p&gt;All the 3 possibility are easily detectable by compiler and I believe for the first two we would like the compiler will decide the variance automatically. We need a solution for the third case only.&lt;/p&gt;
&lt;p&gt;To see the solution, I would like first analyze how we selected which case the given interface belongs to. We analyzed the method signatures in which T is involved:&lt;/p&gt;
&lt;p&gt;1. If in all of them T is 'out' parameter, the interface is covariant.&lt;/p&gt;
&lt;p&gt;2. If in all of them T is 'in' parameter, the interface is contravariant.&lt;/p&gt;
&lt;p&gt;3. If there is a mix - undecidable.&lt;/p&gt;
&lt;p&gt;My solution is to say the compiler how I'm going to use my variable and enable either covariant or contravariant invocations:&lt;/p&gt;
&lt;p&gt;IList&amp;lt;Animal&amp;gt; aa = whatever;&lt;/p&gt;
&lt;p&gt;IList&amp;lt;in Giraffe&amp;gt; ag = aa;&lt;/p&gt;
&lt;p&gt;IList&amp;lt;out Giraffe&amp;gt; agX = aa; //fails to compile&lt;/p&gt;
&lt;p&gt;ag user sees: 'int ag.IndexOf(Giraffe)' and 'object ag[int]'.&lt;/p&gt;
&lt;p&gt;IList&amp;lt;Giraffe&amp;gt; ag = whatever;&lt;/p&gt;
&lt;p&gt;IList&amp;lt;out Animal&amp;gt; aa = ag;&lt;/p&gt;
&lt;p&gt;IList&amp;lt;in Animal&amp;gt; aaX = ag; //fails to compile&lt;/p&gt;
&lt;p&gt;aa user sees: 'int aa.IndexOf(&amp;lt;only null can be passed&amp;gt;)' and 'Animal aa[int]'.&lt;/p&gt;
&lt;p&gt;Now I can say in a type safe manner:&lt;/p&gt;
&lt;p&gt;class X&amp;lt;T&amp;gt; {&lt;/p&gt;
&lt;p&gt;	T _t;&lt;/p&gt;
&lt;p&gt;	void Test(IList&amp;lt;out T&amp;gt; at) {&lt;/p&gt;
&lt;p&gt;		T t = at[0]; //clearly t is 'out' parameter&lt;/p&gt;
&lt;p&gt;	}&lt;/p&gt;
&lt;p&gt;	void Test(IList&amp;lt;in T&amp;gt; at) { //overloaded method!&lt;/p&gt;
&lt;p&gt;		int i = at.IndexOf(_t); //clearly _t is 'in' parameter&lt;/p&gt;
&lt;p&gt;	}&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;p&gt;new X&amp;lt;Animal&amp;gt;().Test(new List&amp;lt;Giraffe&amp;gt;()); //first method is called&lt;/p&gt;
&lt;p&gt;new X&amp;lt;Giraffe&amp;gt;().Test(new List&amp;lt;Animal&amp;gt;()); //second method is called&lt;/p&gt;
&lt;p&gt;Kosta&lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8706944</link><pubDate>Tue, 08 Jul 2008 10:10:16 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8706944</guid><dc:creator>Konstantin Triger</dc:creator><description>&lt;p&gt;I found a very interesting presentation, which shows different options, pros and cons for the implementation: &lt;a rel="nofollow" target="_new" href="http://research.microsoft.com/~akenn/generics/ECOOP06.ppt"&gt;http://research.microsoft.com/~akenn/generics/ECOOP06.ppt&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It's clear that my approach is a variation on Java theme.&lt;/p&gt;
&lt;p&gt;Interestingly enough that in order to create a covariant/contravariant projection in C#, currently one will need to define a special read/write interface. While this is somehow acceptable with one parameter, &amp;nbsp;what is suggested if I have 2 or more, i.e.:&lt;/p&gt;
&lt;p&gt;MyClass&amp;lt;T1,T2,T3&amp;gt;{}&lt;/p&gt;
&lt;p&gt;To cover all the possibilities I need to define 2^3 interfaces. Yes, may be some of them are not useful, but I easily may fail into a situation where I need declare 4-5 interfaces. How is it addressed?&lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8729068</link><pubDate>Sun, 13 Jul 2008 20:33:37 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8729068</guid><dc:creator>John "Z-Bo" Zabroski</dc:creator><description>&lt;p&gt;does this cover situations like ObservableCollection&amp;lt;T1&amp;lt;T2&amp;gt;&amp;gt; ?&lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8776694</link><pubDate>Sun, 27 Jul 2008 01:18:41 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8776694</guid><dc:creator>David Piepgrass</dc:creator><description>&lt;p&gt;I'm curious, on what basis does the CLR decide that &lt;/p&gt;
&lt;p&gt;public interface IN&amp;lt;in U&amp;gt; {}&lt;/p&gt;
&lt;p&gt;public interface IC&amp;lt;X&amp;gt; : IN&amp;lt;IN&amp;lt;IC&amp;lt;IC&amp;lt;X&amp;gt;&amp;gt;&amp;gt;&amp;gt; {}&lt;/p&gt;
&lt;p&gt;is illegal, and does it become legal if U is made invariant?&lt;/p&gt;
&lt;p&gt;OT: why the heck isn't return type covariance on the table? In terms of usefulness, it's in the same ballpark as variance in generics but a vastly simpler concept and dead easy to implement (except for compatibility issues). I've wanted return type covariance for years :(&lt;/p&gt;
</description></item><item><title>Object Oriented F# - Extension Everything</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8937713</link><pubDate>Wed, 10 Sep 2008 01:27:42 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8937713</guid><dc:creator>Matthew Podwysocki's Blog</dc:creator><description>&lt;p&gt;A post by Jeremy Miller caught my eye this morning in regards to extension methods in Javascript . While&lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#8996327</link><pubDate>Sat, 11 Oct 2008 23:10:34 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8996327</guid><dc:creator>Avi Farah</dc:creator><description>&lt;p&gt;Eric,&lt;/p&gt;
&lt;p&gt;your blog is fabulous. &amp;nbsp;I may be too late for the next version of C#. &amp;nbsp;So far Covariance/Contravariance seems to encompas type parameters. &amp;nbsp;If possible expand the scope of Covariance/Contravariance to include delegates.&lt;/p&gt;
&lt;p&gt;--Avi&lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#9006885</link><pubDate>Mon, 20 Oct 2008 09:30:10 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9006885</guid><dc:creator>Rajesh Kumar.</dc:creator><description>&lt;p&gt;One thing i miss from C# is the C++ TypeDef statement.&lt;/p&gt;
&lt;p&gt;That would make the whole thing a bit more readable!, without causing 'expression too complex to parse' in my brain.&lt;/p&gt;
</description></item><item><title>re: Covariance and Contravariance, Part Eleven: To infinity, but not beyond</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#9077959</link><pubDate>Fri, 14 Nov 2008 23:34:26 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9077959</guid><dc:creator>Tim Foley</dc:creator><description>&lt;p&gt;On the subject of return-type covariance, it initially seemd to me like you can try to get the benefit of such a feature for a specific case, like cloning, as follows:&lt;/p&gt;
&lt;p&gt;// covariant interface for cloning:&lt;/p&gt;
&lt;p&gt;interface IClonable&amp;lt;+T&amp;gt; { T clone(); }&lt;/p&gt;
&lt;p&gt;// an example use case in a hypothetical compiler:&lt;/p&gt;
&lt;p&gt;interface IExpression : IClonable&amp;lt;IExpression&amp;gt; {}&lt;/p&gt;
&lt;p&gt;class Add : IExpression, IClonable&amp;lt;Add&amp;gt; { public Add clone(); }&lt;/p&gt;
&lt;p&gt;The clone() method on class Add should be able to satisfy both the IClonable&amp;lt;Expression&amp;gt; and IClonable&amp;lt;Add&amp;gt; interfaces. Clients can clone an arbitrary expression, but if they have something statically known to be an Add then they know that cloning will return another Add.&lt;/p&gt;
&lt;p&gt;Looking at that case, though, it is clearly similar to the case in a previous blog post here that was almost universally agreed to be a compile-time error. The Add class has two different variations of IClonable in its inheritance hierarchy.&lt;/p&gt;
&lt;p&gt;You could claim that Add isn't a problem, since it satisfies the two interfaces with an identical implementation, so casting an Add to an IClonable&amp;lt;object&amp;gt; wouldn't be ambiguous. But what if there had been an Expression base class (instead of an IExpression interface) which supplied a default implementation for IClonable&amp;lt;Expression&amp;gt;.&lt;/p&gt;
</description></item><item><title>WAW!!! What a serie of blog posts for "Covariance and Contravariance" - C# Future...</title><link>http://blogs.msdn.com/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx#9236174</link><pubDate>Thu, 18 Dec 2008 16:22:53 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9236174</guid><dc:creator>Journal of Abu Sayed Mohammad Ismail</dc:creator><description>&lt;p&gt;So nicely step by step blogged by Eric Lippert for &amp;amp;quot;Covariance and Contravariance&amp;amp;quot; as &amp;amp;quot;Fabulous&lt;/p&gt;
</description></item></channel></rss>