С вашим обновлением проблема становится очевидной.List<Work>
не является List<IWork>
.List<T>
не является ковариантным, как дано
interface IWork { }
class Work : IWork { }
class OtherWork : IWork { }
Метод, принимающий List<IWork>
, вполне может попытаться добавить new OtherWork()
, и это было бы совершенно законно во время компиляции.Если для метода был передан List<Work>
, добавление OtherWork было бы абсолютно недопустимым временем выполнения , и поэтому язык не позволяет вам передавать List<Work>
там, где ожидается List<IWork>
.
То, что вы, возможно, захотите сделать, - это метод accept IEnumerable<IWork>
, который позволит вам передать ваш List<Work>
.IEnumerable<T>
является ковариантным (в C # 4), и это может быть потому, что он доступен только для чтения, не будет никаких записей или добавлений в последовательность.
Полный рабочий пример:
namespace Foo
{
public class A
{
// note the change to the signature
public string B(IEnumerable<IWork> workToDo)
{
return workToDo.ToString();
}
static void Main()
{
var type = Type.GetType("Foo.A");
var info = type.GetMethod("B");
var list = new List<Work>();
var x = info.Invoke(Activator.CreateInstance(type), new [] { list });
}
}
public interface IWork { }
public class Work : IWork { }
}
Что касается того, почему это работает для массива, дисперсия массива нарушена.Это позволяет вещи во время компиляции, которые могут быть совершенно опасными во время выполнения.Та же проблема может возникнуть во время выполнения, если у вас есть метод, принимающий IWork[] array
, и вы передаете Work[]
, компилятор позволит вам сделать это в этом случае.Однако было бы совершенно законно (во время компиляции) сказать array[0] = new OtherWork();
, и вы получите исключение времени выполнения.