C# 两个泛型类型之间的转换失败

C# 两个泛型类型之间的转换失败,c#,linq,generics,types,generic-programming,C#,Linq,Generics,Types,Generic Programming,我正在尝试创建一个对象类型MyObject,其linq表达式类型为T。我的类声明T的值必须是BaseModel类型,它是我创建的对象。以下是MyObject的构造方式: public class MyObject<T> where T : BaseModel { public Type MyType; public Expression<Func<T, bool>> MyExpression; } 我的对象在泛型静态类中使用: public

我正在尝试创建一个对象类型MyObject,其linq表达式类型为T。我的类声明T的值必须是BaseModel类型,它是我创建的对象。以下是MyObject的构造方式:

public class MyObject<T> where T : BaseModel
{
    public Type MyType;

    public Expression<Func<T, bool>> MyExpression;
}
我的对象在泛型静态类中使用:

public static class MyStaticClass
{
    private static Dictionary<MyObject<BaseModel>, string> MyDictionary = new Dictionary<MyObject<BaseModel>, string>();

    public static AddMyObjectsToDictionary(List<MyObject<BaseModel>> myObjects)
    {
        //CODE
    }

    //REST OF CODE
}
然后,当我的应用程序加载时,会在此处抛出以下错误:

与名称空间一起引发的确切错误消息,以显示每个对象位于哪个项目中:

无法从“ProjectANamespace.MyObject”转换为“ProjectANamespace.MyObject”

我需要能够在MyModel中创建一个泛型表达式,但是我不能在MyStaticClass中指定MyModel,因为它是一个泛型类,与BaseModel一起位于另一个项目中


有人知道如何解决这个问题吗

要做到这一点,我认为您需要使用C4+的特性。特别是,我认为您需要使用修饰符。经过一些测试,我发现这对类不起作用。但是,如果在模式中引入接口,就可以实现这一点。例如,以下编译

public class Base
{

}

public class Derived : Base
{

}

public interface IWrapper<out T> where T : Base
{

}

public class Wrapper<T> : IWrapper<T> where T : Base
{

}

public static class Methods
{
  public static void Test()
  {
    var obj = new List<IWrapper<Base>>();
    obj.Add(new Wrapper<Derived>());
  }
}
MyObject不是MyObject,就像List不是List一样。它在泛型之外也起同样的作用——一般的概念称为方差,描述类型的有效替换。因为MyObject对于T既不是共变的也不是逆变的,所以对于任何不同的T和U,MyObject都不可能是MyObject

接口和委托中的泛型类型参数可以是共变变量和逆变变量,但不能同时是共变变量和逆变变量。例如,Func是反变量,因为可以替换从T派生的类型而不是T本身。因此,Func可以转换为Func,就像MyModel可以作为参数而不是BaseModel传递一样,但反之亦然。类似地,Func相对于T是反变量,相对于U是协变量-您不能从返回类型为字符串的函数返回对象

因此,即使您将定义更改为使用接口添加方差,您也只能获得反向方差,而不能获得所需的协方差。太糟糕了,没有安全的方法


相反,如果您需要一个非通用接口,只需添加一个非通用接口即可。就这样。您将使用List而不是List,您可以根据需要使用List,可能是通过强制转换,或者只是公开简单表达式而不是表达式。

这就是确切的错误消息吗?我希望收到一条消息,它无法将MyObject转换为MyObject,因为BaseModel是不变的。不,确切的错误是:无法从“ProjectANamespace.MyObject”转换为“ProjectANamespace.MyObject”。我包含名称空间以显示在不同项目中定义的对象,这更有意义。那么问题是因为MyObject是不变的,而不是因为它对主程序不可见。这不会起作用,因为类是不变的,而Func中的t参数是逆变的。非常正确。我只是测试了一下,发现了这一点。我将编辑以匹配。
List<MyObject<BaseModel>> myObjects = new List<MyObject<BaseModel>>();

myObjects.Add(new MyObject<MyModel>()
{
    MyType = typeof(MyModel),
    MyExpression = p => p.Name == "myname"
});

MyStaticClass.AddMyObjectsToDictionary(myObjects);
public class Base
{

}

public class Derived : Base
{

}

public interface IWrapper<out T> where T : Base
{

}

public class Wrapper<T> : IWrapper<T> where T : Base
{

}

public static class Methods
{
  public static void Test()
  {
    var obj = new List<IWrapper<Base>>();
    obj.Add(new Wrapper<Derived>());
  }
}