逆变/协方差 - 无法将类转换为接口



>我有以下代码

public interface IInterface
{
}
public class GenericClass<TSomeClass>
where TSomeClass : class
{
public TSomeClass SomeMethod(TSomeClass someClass = null)
{
return SomeClass.SomeClassStaticInstance;                   //ERROR:Cannot implicitly convert type 'SomeClass' to 'TSomeClass'
return (TSomeClass)SomeClass.SomeClassStaticInstance;       //ERROR:Cannot convert type 'SomeClass' to 'TSomeClass'
return SomeClass.SomeClassStaticInstance as TSomeClass;     //Works when "where TSomeClass : class" clause added
}
}
public class SomeClass : IInterface
{
public static SomeClass SomeClassStaticInstance = new SomeClass();
}

它会生成相应行的注释中记录的编译时错误。

我想知道为什么我不能只使用产生错误的第一行?SomeClass实现了IInterface但我不得不弄乱as关键字。

我尝试将GenericClass<TSomeClass>更改为GenericClass<out TSomeClass>但随后我收到另一个编译时错误Only interface and delegate type parameters can be specified as variant.即使我删除了where TSomeClass : class子句,该错误仍然存在。

我错过了什么...它显然有效,因为我可以使用where TSomeClass : class子句和return SomeClass.SomeClassStaticInstance as TSomeClass;语句"强制它"!

我确实需要where TSomeClass : class否则我会收到另一个编译时错误TSomeClass someClass = null......A value of type '<null>' cannot be used as a default parameter because there are no standard conversions to type 'TSomeClass'.

所以基本上是编译时错误一直向下!谢谢。

I would like to know why I can't just use the first line that generates an error? SomeClass implements IInterface but I have to mess around with the as keyword.

您必须使用(TSomeClass)YourInstance因为语言旨在防止对转换泛型参数的任何假设。阅读更多。

因为无法预测参数类型的隐式转换 TSomeClass,除非您放置继承类型较少的约束,例如接口。应将约束更改为差异where TSomeClass : IInterface

使用as键有效,因为如果类型不兼容,它将返回 null,这就是您需要class约束的原因。将约束更改为接口后,as语句将变为无效。

在工厂方法中,应返回IInterface以便泛型类型参数可以接受直接强制转换。

我相信这会起作用:

public interface IInterface
{
}
public class GenericClass<TSomeClass>
where TSomeClass : IInterface
{
//Not sure what the input parameter is for?
public IInterface SomeMethod(TSomeClass someClass = null)
{
return SomeClass.SomeClassStaticInstance;                  
}
}
public class SomeClass : IInterface
{
public static IInterface SomeClassStaticInstance = new SomeClass();
}

然而,正如其他人所指出的,这里的问题实际上是在这种情况下使用泛型的用途 - 是否有更好的选择来构建你的代码?

很难从您给我们的结构中判断这样做的目的是什么。

目前你唯一的约束是TSomeClass是一个类,所以如果你要用一个不是SomeClass的类型或从它派生的类型来实例化GenericClassreturn SomeClass.SomeClassStaticInstance;显然是行不通的。

例如:

var genericClass = new GenericClass<SomeRandomClass>(); // fine
var randomClass = genericClass.SomeMethod(new SomeRandomClass()); // not fine, a SomeClass is returned!

我不确定IInterface目前在这一切中的位置?

也许你希望 SomeMethod 返回一个实现IInterface的对象;如果是这样,你需要进一步约束你的泛型类型,并让你的方法返回一个IInterface

public class GenericClass<TSomeClass> where TSomeClass : class, IInterface
{
public IInterface SomeMethod(TSomeClass someClass = null)
{
return SomeClass.SomeClassStaticInstance; //This now compiles!
}
}

至于return SomeClass.SomeClassStaticInstance as TSomeClass;最初为什么有效,这只是一个巧合。

as是一个安全的强制转换运算符,如果尝试的转换失败,它将返回null。由于TSomeClass约束为类,因此null返回值将有效。但是,如果您指定的泛型类型未SomeClass,则始终返回null

最新更新