C#在'out'通用修饰符中的无效差异

时间:2018-03-27 17:18:21

标签: c# .net generics interface covariance

我正在尝试使用out generic修饰符构建一个通用项列表,但是我收到错误'无效方差:类型参数'T'必须在'ITestInterface.Value'上不变地有效。 'T'是协变的。'

我在尝试存储值类型以及引用类型时也遇到错误。

我想要一个通用对象列表,每个对象都有不同的类型T,并在界面中使用类型T.

有人能告诉我我做错了吗?

public MainWindow()
{
   var list = new List<ITestInterface<object>>();
   list.Add(new Test<string>());
   list.Add(new Test<int>());

   foreach (var item in list)
   {
      var x = item.Value;
   }
}

public interface ITestInterface<out T>
{
   T Value { get; set; }
}

public class Test<T> : ITestInterface<T>
{
   public T Value { get; set; }
}

我一直在https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-generic-modifierCollection of derived classes that have generic base class工作。

感谢任何人的帮助!

更新

感谢所有帮助我了解这一领域的人。我现在看到我误解了out / in泛型修饰符的用法。 Invalid variance: The type parameter 'T' must be contravariantly valid on 'UserQuery.IItem<T>.ItemList'. 'T' is covariant中的问题和答案肯定与我尝试做的大多数事情有关,但我也试图将参考和值类型添加为类型参数。

我发现的一个(略微可疑的)解决方法是从类中删除泛型,并在返回类实例的静态方法中使用它们。绝对不是类型安全的,但它确实允许使用引用和值类型:

public MainWindow()
{
    var list = new List<Test>();
    list.Add(Test.Create<string>("test"));
    list.Add(Test.Create<int>(5));

    foreach (var item in list)
    {
        var x = item.Value;
    }
}

public class Test
{
    public object Value { get; set; }
    public Type ValueType { get; set; }

    public static Test Create<T>(T value)
    {
        return new Test
        {
            Value = value,
            ValueType = typeof(T),
        };
    }

    public T GetValue<T>()
    {
        if (typeof(T) == ValueType)
            return (T)Convert.ChangeType(Value, typeof(T));
        else
            throw new InvalidOperationException();
    }
}

1 个答案:

答案 0 :(得分:0)

你可以尝试这样吗?这是基于Jeroen Mostert上面的评论和一些R&amp; D.

但是这不允许你添加值类型。 string可以作为参考类型,但不是intfloat等。

public interface ITestInterface<out T>
{
     T GetValue();
}
public class Test<T> : ITestInterface<T>
{
    public T Value { get; set; }
    public T GetValue()
    {
        throw new NotImplementedException();
    }

    public void SetValue(T para)
    {
        Value = para;
    }
}