I have a routine
public void SomeRoutine(List<IFormattable> list) { ... }
I then try to call this routine
List<Guid>list = new List<Guid>();
list.Add(Guid.NewGuid());
SomeRoutine(list);
And it fails with a compile-time error. System.Guid implements IFormattable, but the error I get is
cannot convert from 'System.Collections.Generic.List' to 'System.Collections.Generic.List'
NOTE: You will get the same error if you just use an array of Guids. Generics is NOT the cause....
But! Given this
public void SomeRoutine2(IFormattable obj) { ... }
and this
Guid a = Guid.NewGuid();
SomeRoutine2(a);
It compiles! So the question is WHY? Why am I able to pass a Guid object (which implements IFormattable) into a routine that accepts an object of IFormattable, but when I try to expand that to a collection (a generic list, or an array, or anything else), I get a conversion error?
I have had a heck of a time finding an answer, and I figured this would be the best place to go.
C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...
%d is used to print decimal(integer) number ,while %c is used to print character . If you try to print a character with %d format the computer will print the ASCII code of the character.
In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.
C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.
This is that whole covariance thing everyone talks about. It will work in .NET 4.0.
See here: http://blogs.msdn.com/charlie/archive/2008/10/28/linq-farm-covariance-and-contravariance-in-visual-studio-2010.aspx
Some more reading:
http://www.infoq.com/news/2008/08/GenericVariance;jsessionid=188695B18864997E8D360E0EEED5983E
http://blogs.msdn.com/lucian/archive/2008/10/02/co-and-contra-variance-how-do-i-convert-a-list-of-apple-into-a-list-of-fruit.aspx
This is a classic generics use-case; try:
public static void SomeRoutine<T>(IList<T> list) where T : IFormattable
{ ... }
Now inside SomeRoutine
you have access to all the IFormattable
members, but it will work with:
List<Guid>list; ...
SomeRoutine(list); // note no need to specify T
Edit: I've additionally blogged on the differences between 4.0 covariance and generics for this scenario.
The problem is that a List<IFormattable> is not only a collection from which you can read some IFormattables, it's also a collection to which you can add IFormattables. A List<Guid> meets the first requirement, but not the second. What if SomeRoutine was
public void SomeRoutine(List<IFormattable> list)
{
list.Add(5);
}
That Int32 is an IFormattable, so the method should be able to add it to the List<IFormattable> that it asked for. That's not going to work if the compiler lets you pass in your List<Guid>.
The new C# 4.0 features that BFree refers to will let you tell the compiler when these things are safe. You can say either
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With