我有一个班级:
public class ClassA<T>
{
public T Value {get; set;}
public string Description {get; set;}
}
ClassA可以具有任何类型的值,但是:无论类型值如何,我都需要能够设置任何ClassA的其他属性。所以我有一个方法:
public void DoWork(ClassA<object> source, ClassA<object> destination)
{
destination.Description = source.Description;
}
然而,当我尝试这样做时,我得到一个运行时错误,说:
无法从ClassA<DateTime>
转换为ClassA<object>
我认为任何东西都可以作为一个对象传递......我在网上看到了类似的东西,也许我只是没有让关键字正确。
有人有任何建议吗?
由于
答案 0 :(得分:4)
你将无法做到这一点。
如果您可以将ClassA<int>
传递给接受ClassA<object> wrapper
的方法,则该方法可以调用wrapper.Value = "not an integer";
。那会发生什么?您只需将字符串设置为只能保存整数的对象。由于编译器知道它不能强制执行你可以放置它的东西,它只是不允许你在第一时间传递该对象。
至于实际的解决方案,我想到了两个。
如果这是一个选项,你可以使你的方法通用:
public void DoWork<TSource, TDestination>(ClassA<TSource> source, ClassA<TDestination> destination)
{
destination.Description = source.Description;
}
或者你可以建立一个协变界面:
public interface IWrapper<out T>
{
T Value {get;}
string Description {get;set;}
}
public class ClassA<T> : IWrapper<T>
{
//...
}
public void DoWork(IWrapper<object> source, IWrapper<object> destination)
{
destination.Description = source.Description;
}
对于DoWork
方法,您实际上甚至没有使用Value
,因此您可以使界面非通用,非协变,只需删除Value
即可。这里的优点是您可以使用该接口来访问具有公共基类型的任意数量ClassA
个对象的值属性。
答案 1 :(得分:4)
如果您只需要能够使用各种泛型类型,则可以为每个参数指定不同的类型,例如。
public void Work<TSource, TDestination>(ClassA<TSource> source, ClassA<TDestination> destination)
{
destination.Description = source.Description;
}
但是,看起来你真正的问题是你在泛型类上有共同属性,你可以通过使用通用接口来消除通用部分,例如。
public interface IClassA
{
string Description { get; set; }
}
public class ClassA<T> : IClassA
{
...
}
public void DoWork(IClassA source, IClassA destination)
{
destination.Description = source.Description;
}
答案 2 :(得分:2)
这与扩展方法没有任何关系。它与通用方差有关。最简单的是这样看:
ClassA<DateTime> x = new ClassA<DateTime>();
ClassA<Object> y = x;
这将无法以相同的方式编译。
从C#4开始,对通用差异有一些有限的支持,但是:
有关详细信息,请参阅MSDN,或Eric Lippert's blog posts。
这解释了为什么它不起作用。至于如何修复它 - 根据Jason的回答使扩展方法通用可能是最简单的方法。
请注意,目前您还没有扩展方法 - 您需要在顶级非泛型静态类中声明它,如下所示:
public static void DoWork<T>(this ClassA<T> source, ClassA<T> destination)
{
destination.Description = source.Description;
}
答案 3 :(得分:0)
我认为你的意思是:
public void DoWork<T>(ClassA<T> source, ClassA<T> destination)
{
destination.Description = source.Description;
}