的List<>的函数功能:LT;> S,与普通的返回类型,但为什么编译出错?函数、但为、类型、普通

2023-09-07 14:51:12 作者:社会小仙女

这是一个有点冗长的问题,所以请多多包涵。

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>
        };