2

Consider the code:

using System.Collections.Generic;
namespace TestingTypes
{
    class Program
    {
        static void Main(string[] args)
        {
            var strings = new List<string>();               
            INeedToPassThisMethodAListOfObjects(strings as List<object>);
        }

        static void INeedToPassThisMethodAListOfObjects(List<object> objects) { }
    }
}

1>------ Build started: Project: TestingTypes, Configuration: Debug Any CPU ------
1>c:\users\[censored]\TestingTypes\Program.cs(9,41,9,64): error CS0039: Cannot convert 
type 'System.Collections.Generic.List<string>' to 
'System.Collections.Generic.List<object>' via a reference conversion, boxing 
conversion, unboxing conversion, wrapping conversion, or null type conversion

You might say that a List<string> is a List<object>, since a string is an object and C# 4 is supposed to support covariance in generic types.

  • Why does the compiler say it can't convert the type?
  • How do I pass "strings" to the method?
James Orr
  • 5,005
  • 7
  • 39
  • 63

3 Answers3

3

You're getting the error because a List<string> is not a List<object>.

You can call list.Add(new TextBox()) on List<object> but, obviously, the same call doesn't work on List<string>.

C# Generics only allow for Covariance if the generic type is immutable (which is my the cast from List to IEnumerable works).

If you need to pass the list to a method, you could try passing

listOfStrings.Cast<object>();

On the downside, if you use that solution, any modifications made to the list inside the method call will not be reflected in the original list (because the call to Cast creates a new list).

If you have control of the method INeedToPassThisMethodAListOfObjects and that method only needs to iterate over the collection rather than modify it, you can change the parameter type to be IEnumerable<object> in which case you'd simply be able to pass your List<string> without any issues.

Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
3

Interfaces can be variant; classes cannot. See here for the explanation.

Your code will work if you pass the strings collection uncasted and change the declaration to be

static void INeedToPassThisMethodAListOfObjects(IEnumerable<object> objects) { }

However, that depends on whether you need a List within this function.

Community
  • 1
  • 1
Tim Rogers
  • 21,297
  • 6
  • 52
  • 68
  • Thanks to everybody, Tim the prize goes to you for being the first to note about class type variance versus interfaces. – James Orr Oct 24 '12 at 17:17
  • Didn't I note this first? I don't care about points though so leave it like that :) – Pluc Oct 24 '12 at 19:34
  • Ah Pluc you're absolutely right, you had Tim Rogers beat by 90 seconds now that I look. Thanks for helping me. – James Orr Oct 25 '12 at 16:17
  • 1
    If @BarryFandango needs list functionality, in .NET 4.5 and later he can use `void Method(IReadOnlyList objects)`. The interface `IReadOnlyList` is covariant in `T`, and `List` and `T[]` and others implement `IReadOnlyList`. – Jeppe Stig Nielsen Dec 05 '13 at 11:16
2

You have to convert the strings to objects. Theres a nice LINQ method to do so.

var strings = new List<string>();               
INeedToPassThisMethodAListOfObjects(strings.Cast<object>());

Edit

According to your own link,

In C#, variance is supported in the following scenarios:

  • Covariance in arrays (since C# 1.0)

  • Covariance and contravariance in delegates, also known as “method group variance” (since C# 2.0)

  • Variance for generic type parameters in interfaces and delegates (since C# 4.0)

So IEnumerable would accept List

Community
  • 1
  • 1
Pluc
  • 2,909
  • 1
  • 22
  • 36