C# 两个泛型类型之间的转换失败
我正在尝试创建一个对象类型MyObject,其linq表达式类型为T。我的类声明T的值必须是BaseModel类型,它是我创建的对象。以下是MyObject的构造方式: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
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>());
}
}