Ric*_*ett 16 c# generics .net-4.0 func
这是一个冗长的问题,所以请耐心等待.
我需要在一组字符串和每个字符串的相应泛型方法调用之间创建一个映射.但是我遇到了一个编译问题,向下解释.
在我的场景中,我正在使用a Dictionary<>,但问题同样存在于a List<>.为简单起见,我List<>在下面的示例中使用了a .
考虑这三个类:
public abstract class MyBase { /* body omitted */  }
public class MyDerived1 : MyBase { /* body omitted */  }
public class MyDerived2 : MyBase { /* body omitted */  }
还有一些其他类的方法:
public class Test
{
    public T GetT<T>() where T : MyBase { /* body omitted */ }
}
在另一个课程中,我可以声明List<Func<MyBase>>如下:
public class SomeClass
{
    public void SomeFunc()
    {
        var test = new Test();
        var list1 = new List<Func<MyBase>>
            {
                test.GetT<MyDerived1>,
                test.GetT<MyDerived2>
            };
    }
}
这一切都很好.
但是,如果我想要一个返回如下通用类的函数,该怎么办:
public class RetVal<T> where T : MyBase { /* body omitted */ }
public class Test
{
    public RetVal<T> GetRetValT<T>() where T : MyBase
    {
        return null;
    }
}
我想List<>用这个函数创建一个等价物.即列表>>?
public class Class1
{
    public void SomeFunc()
    {
        var test = new Test();
        var list2 = new List<Func<RetVal<MyBase>>>
            {
                test.GetRetValT<MyDerived1>, // compile error
                test.GetRetValT<MyDerived2> // compile error
            };
    }
}
我得到编译错误Expected a method with 'RetVal<MyBase> GetRetValT()' signature.
那么,有什么方法可以解决这个问题,还是有一种替代方法可以用来创建我的字符串......泛型方法调用映射?
Str*_*ior 16
C#仅允许接口上的协方差.这意味着您无法自动投射RetVal<MyDerived1>到RetVal<MyBase>.如果RetVal应该是协变的,为它创建一个接口,如下所示:
public interface IRetVal<out T>
{
}
public class RetVal<T> : IRetVal<T> where T : MyBase { /* body omitted */ }
public class Test
{
    public IRetVal<T> GetRetValT<T>() where T : MyBase
    {
        return null;
    }
}
那么这段代码将起作用:
    var list2 = new List<Func<IRetVal<MyBase>>>
        {
            test.GetRetValT<MyDerived1>,
            test.GetRetValT<MyDerived2>
        };
问题是泛型的经典协方差/逆变.你假设因为MyDerived1和MyDerived2继承MyBase,一个RetVal<MyDerived1>继承自RetVal<MyBase>,而不是继承.
解决此问题的最简单方法可能是将代码更改为:
var list2 = new List<Func<RetVal<MyBase>>>
        {
            () => (MyBase)test.GetRetValT<MyDerived1>,
            () => (MyBase)test.GetRetValT<MyDerived2>
        };
或者更好,正如JS在评论中指出的那样,RetVal<T>如果可能的话,只需改为协变:
public interface IRetVal<out T> { ... }
public class RetVal<T> : IRetVal<T> { ... }
| 归档时间: | 
 | 
| 查看次数: | 3437 次 | 
| 最近记录: |