这是一个有点冗长的问题,所以请多多包涵。
This is a bit of a lengthy question, so please bear with me.
我需要创建一组字符串和相应的通用方法调用每串之间的映射。不过我碰到一个编译的问题,解释低了下去。
I need to create a mapping between a set of strings and corresponding generic method calls for each string. However I've run into a compile issue, explained lower down.
在我的情况,我使用的是词典<>
,但存在同样的名单,其中的问题;>
。为简单起见,我使用的是名单,其中;>
在下面的例子
In my scenario I am using a Dictionary<>
, but the issue exists equally for a List<>
. For simplicity I'm using a List<>
in the example below.
考虑以下三类:
public abstract class MyBase { /* body omitted */ }
public class MyDerived1 : MyBase { /* body omitted */ }
public class MyDerived2 : MyBase { /* body omitted */ }
和一些其他类中的方法:
And a method in some other class:
public class Test
{
public T GetT<T>() where T : MyBase { /* body omitted */ }
}
在另一个类,我可以声明名单,其中,Func键&LT; MyBase&GT;&GT;
是这样的:
In another class, I can declare a List<Func<MyBase>>
like this:
public class SomeClass
{
public void SomeFunc()
{
var test = new Test();
var list1 = new List<Func<MyBase>>
{
test.GetT<MyDerived1>,
test.GetT<MyDerived2>
};
}
}
这是一切优秀和幸福。
但是,如果我想有一个返回泛型类这样的功能:
But, what if I want to have a function that return a generic class like this:
public class RetVal<T> where T : MyBase { /* body omitted */ }
public class Test
{
public RetVal<T> GetRetValT<T>() where T : MyBase
{
return null;
}
}
和我想创建一个相当于名单,其中;&GT;
使用此功能。即一个列表>>?
And I want to create an equivalent List<>
using this function. i.e. a 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
};
}
}
我得到的编译的错误预期与'将RetVal℃的方法; MyBase&GT; GetRetValT()'签名
。
那么,有没有解决这个办法,或者是有,我可以用于创建我的串...泛型方法调用的映射?
So, is there any way around this, or is there an alternative approach that I can use for creating my string...generic method call mappings?
C#只允许在接口上的协方差。这意味着你可以不投一个将RetVal&LT; MyDerived1&GT;
到将RetVal&LT; MyBase&GT;
自动。如果将RetVal
应该是协变的,因为它创建一个接口,像这样:
C# only allows covariance on interfaces. That means you cannot cast a RetVal<MyDerived1>
to a RetVal<MyBase>
automatically. If RetVal
should be covariant, create an interface for it, like so:
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;
}
}
那么这code将工作:
Then this code will work:
var list2 = new List<Func<IRetVal<MyBase>>>
{
test.GetRetValT<MyDerived1>,
test.GetRetValT<MyDerived2>
};