2

I have generic class with constraint where T : IEnumerable<object>. I expected that I can use any type instead object. But when I try to create an instance of my generic class with List<SomeValueType> Visual studio gives me an error like There is no implicit reference conversion from System.Collections.Generic.List<ConsoleApp.Program.ValueType>' to System.Collections.Generic.IEnumerable<object>'. So my question is: why I can't use both value and reference types in this case even though they're both inherited from object?

    static void Main(string[] args)
    {
        var example1 = new GenericClass<List<ReferenceType>>(); // it's ok

        // There is no implicit reference conversion 
        // from 'System.Collections.Generic.List<ConsoleApp.Program.ValueType>'
        // to 'System.Collections.Generic.IEnumerable<object>'
        var example2 = new GenericClass<List<ValueType>>(); 
    }

    public class GenericClass<T> where T : IEnumerable<object>
    {

    }

    public class ReferenceType
    {

    }

    public struct ValueType
    {

    }
Shadr
  • 214
  • 1
  • 12
  • There's a flaw in the logic. The assumption here seems to be ValueType is an object so an IEnumerable is an IEnumerable. But it's not, this show when we use a list example `var list = new List();` and then do something like `list.Add(new object());` you can't do this on a List of ValueType but that would be allowed if we did `var list = new List()`. So we see that a IList is not the same as an IList –  Jan 31 '19 at 14:07
  • @Knoop That doesn't really apply. `IEnumerable` doesn't let you *add* something. (If this was the case, OP's first example wouldn't work.) – Rawling Jan 31 '19 at 14:08
  • @Rawling I was trying to give an intuitive example on why the basic logic is flawed –  Jan 31 '19 at 14:09
  • You can simplify it to `IEnumerable list = new List();` which is not allowed as opposed to `IEnumerable list = new List(); ` – Tim Schmelter Jan 31 '19 at 14:10
  • A Value Type holds the data within its own memory allocation and a Reference Type contains a pointer to another memory location that holds the real data. So an object is a reference type a value type is not, therefore you cannot use it. http://net-informations.com/faq/general/valuetype-referencetype.htm – Shak Ham Jan 31 '19 at 14:12
  • @Rango in my opinion the add to a list is more intuitive. My assumption would be that most people would look at that and go 'hey, ofc you can't add an object to a list of a specific type!' The `IEnumerable list = new List();` in my opinion is much closer to what visual studio is already stating: `IEnmuberable is not the same as IEnumerable` which the op was unclear on. I just hope I didn't make the whole thing more complicated, since the whole goal was to give some insights. –  Jan 31 '19 at 14:20
  • 2
    @Knoop But `IEnumerable` *does actually support covariance* on its generic argument, because it doesn't ever use the generic type as input in any operation, unlike a list, which is invariant because it uses its generic type argument for both input and output. C# just doesn't support variance on value types, only reference types. Saying an argument is easier to understand is pointless when *it's just wrong*. Of course, I don't know why you think "C# doesn't support covariance on value types" is a complex explanation (it even has the benefit of being correct). – Servy Jan 31 '19 at 14:22
  • @Servy I did not know that, that's very interesting. Thanks for the explaination, makes sense to me now:-) –  Jan 31 '19 at 14:25

0 Answers0