通用c#铸造
上面是一个实现接口ISample的类。使用泛型,我添加了下面的方法来将给定类型的对象转换为另一种类型通用c#铸造,c#,.net,generics,C#,.net,Generics,上面是一个实现接口ISample的类。使用泛型,我添加了下面的方法来将给定类型的对象转换为另一种类型 interface ISample { int Id { get; set; } } public class MyClass : ISample { public int Id { get; set; } public string Name { get; set; } } private TResult示例(TSource
interface ISample
{
int Id { get; set; }
}
public class MyClass : ISample
{
public int Id
{
get;
set;
}
public string Name { get; set; }
}
private TResult示例(TSource源)
where TSource:TResult
{
返回(TResult)(来源);
}
使用泛型如何实现与给定ISample对象相反的效果我想将其转换回MyClass对象,其中ISample是TSource,TResult是MyClass,TResult实现TSource。您只需从
private TResult Sample<TSource, TResult>(TSource source)
where TSource : TResult
{
return (TResult)(source);
}
到
最终的代码可能看起来像
where TResult : TSource
private-TResult-to接口(TSource-source),其中TSource:TResult
{
返回源;
}
私有TResult FromInterface(TSource source),其中TResult:TSource
{
返回源作为TResult;
}
请注意,如果“source”参数不是TResult类型或不是从TResult继承的,则FromInterface函数将抛出InvalidCastException
编辑:
请参阅Lajos Arpad的答案。您只需从
private TResult Sample<TSource, TResult>(TSource source)
where TSource : TResult
{
return (TResult)(source);
}
到
最终的代码可能看起来像
where TResult : TSource
private-TResult-to接口(TSource-source),其中TSource:TResult
{
返回源;
}
私有TResult FromInterface(TSource source),其中TResult:TSource
{
返回源作为TResult;
}
请注意,如果“source”参数不是TResult类型或不是从TResult继承的,则FromInterface函数将抛出InvalidCastException
编辑:
请参阅Lajos Arpad的答案。编译器不会事先知道您打算从
TSource
向下转换到TResult
。您需要将TSource
实例强制转换为肯定是TResult
超类的某个对象,因此首先需要将TSource
强制转换为对象
:
private TResult ToInterface<TSource, TResult>(TSource source) where TSource : TResult
{
return source;
}
private TResult FromInterface<TSource, TResult>(TSource source) where TResult : TSource
{
return source as TResult;
}
编辑:
正如@Zdeněk Jelínek在评论部分指出的,Eric Lippert为此写了一篇博客。编译器不会事先知道您打算从
TSource
向下转换到TResult
。您需要将TSource
实例强制转换为肯定是TResult
超类的某个对象,因此首先需要将TSource
强制转换为对象
:
private TResult ToInterface<TSource, TResult>(TSource source) where TSource : TResult
{
return source;
}
private TResult FromInterface<TSource, TResult>(TSource source) where TResult : TSource
{
return source as TResult;
}
编辑:
正如@Zdeněk Jelínek在评论部分指出的,Eric Lippert为此写了一篇博客。你不能这样做,因为当你有一个
的实例是简单的,谁能保证它实际上是MyClass
的实例,而不是实现该接口的任何其他实例?不管怎样,你为什么会有这种方法?如果TSource
继承了TResult
(这是您在那里设置的),那么任何TSource
类型的对象都可以隐式地转换为TResult
。然而,我确实认为,如果您将其反转(TResult
继承自TSource
),您可以在某种程度上保证转换是可能的;或者至少你会遇到编译器错误而不是运行时异常。你不能这样做,因为当你有一个ISample
的实例时,谁能保证它实际上是MyClass
的实例,而不是实现该接口的任何其他实例?不管怎样,你为什么会有这种方法?如果TSource
继承了TResult
(这是您在那里设置的),那么任何TSource
类型的对象都可以隐式地转换为TResult
。然而,我确实认为,如果您将其反转(TResult
继承自TSource
),您可以在某种程度上保证转换是可能的;或者至少你会遇到编译器错误而不是运行时异常。你可以使用castas
来避免异常,让函数的用户选择如何处理无效的cast而不是抛出异常。没错,但问题在于为层次结构中的类型之间的强制转换创建一个通用解决方案,而不是处理无效强制转换。我同意这并不理想。您可以使用castas
来避免异常,并让函数的用户选择如何处理无效的cast,而不是抛出异常。这是真的,但问题在于为层次结构中的类型之间的强制转换创建一个通用解决方案,而不是处理无效的强制转换。我同意这不理想。你的解决方案是正确的。Eric Lippert在博客中对此进行了更广泛的解释:@ZdeněkJelínek感谢您的投入,我已经在答案中添加了这些有价值的细节。您的解决方案是正确的。Eric Lippert在博客中对此进行了更广泛的解释:@ZdeněkJelínek感谢您的投入,我在答案中添加了这些有价值的细节。