4

我有一堂课:

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>

我认为任何东西都可以作为对象传递......我已经在网上寻找类似的东西,也许我只是没有得到正确的关键字。

有人有什么建议吗?

谢谢

4

4 回答 4

4

你将无法做到这一点。

如果您可以将 a 传递给ClassA<int>接受 a 的方法,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具有公共基类型的任意数量对象的值属性。

于 2012-12-14T15:16:07.617 回答
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;
}
于 2012-12-14T15:19:02.603 回答
2

这与扩展方法没有任何关系。它与通用方差有关。像这样看到它是最简单的:

ClassA<DateTime> x = new ClassA<DateTime>();
ClassA<Object> y = x;

这将无法以相同的方式编译。

从 C# 4 开始,对泛型变化的支持有限,但是:

  • 仅适用于接口和委托
  • 仅适用于引用类型
  • 仅在明确声明的地方

有关更多详细信息,请参阅MSDN,或Eric Lippert 的博客文章

这就解释了为什么它不起作用。至于如何解决它-根据 Jason 的回答使扩展方法通用可能是最简单的方法。

请注意,目前,您甚至还没有扩展方法 - 您需要在顶级非泛型静态类中声明它,如下所示:

public static void DoWork<T>(this ClassA<T> source, ClassA<T> destination)
{
    destination.Description = source.Description;
}
于 2012-12-14T15:15:38.093 回答
0

我假设你的意思是:

public void DoWork<T>(ClassA<T> source, ClassA<T> destination)
{
  destination.Description = source.Description;
}
于 2012-12-14T15:11:43.627 回答