将泛型传递给方法

时间:2012-12-14 15:08:36

标签: c# generics

我有一个班级:

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 个答案:

答案 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;
}