C#(+ WPF)将泛型类转换为非泛型的问题

时间:2010-01-08 21:36:36

标签: c# generics casting

我必须诚实地说,我对铸造并不是很了解,但我认为这样可行。

我有一个通用课程测试:

public class Test<T,U>
{
     T variable1;
     U variable2;

     //etc.
}

我需要在WPF视图中使用这个类,因为你不能在WPF中创建通用视图(多么可爱)我想:让我们使用Test<object, object&gt;对于视图,因为我只关心在视图中使用变量的字符串表示。

所以我试试:

  Test<Foo, Bar> test = new Test<Foo, Bar>();
  return test as Test<object, object>;

但这给了我:

  Error 1   Cannot convert type 'DomainModel.Tests.Test<T,U>' 
  to 'DomainModel.Tests.Test<object,object>' via a reference conversion, boxing
  conversion, unboxing conversion, wrapping conversion, or null type conversion

我认为每个对象都必须可以转换为对象?

无论如何,我现在很困惑如何在WPF中使用泛型类......

任何指针都在正确的方向?

2 个答案:

答案 0 :(得分:5)

这是一个通用的差异问题。 C#3不允许通用参数类型的差异:因此,IEnumerable<string>IEnumerable<object>不兼容。对于C#4中的安全方案,将放宽此限制。但这对您的情况没有帮助,因为C#4仅支持接口或委托的差异。即使C#的未来版本允许类的泛型差异,仍然可能无法帮助您,因为Test<object, object>是安全的强制转换并不清楚:假设variable1有一个setter:

Test<string, string> t = new Test<string, string>();
Test<object, object> bad_t = t as Test<object, object>;
bad_t.variable1 = new Llama();  // but variable1 should contain only strings!

然而,您可以将“Test<string, string>”投射到object

object good_t = t;  // don't even need a cast

WPF绑定仍然可以通过反射访问其属性。

或者,定义一个非泛型接口,提供您需要的功能(在您的情况下为“变量的字符串表示”):

public interface IPresentV1AndV2  // stupid name of course
{
  public string Variable1AsString { get; }
  public string Variable2AsString { get; }
}

并在您的泛型类上实现此功能。然后,您可以通过接口成员访问字符串值。 (显然,这个特定的接口示例是愚蠢地绑定到实现,实际上你会给它一个名称和成员,反映它暴露的数据的业务含义。)

答案 1 :(得分:3)

版本3.0的C#不支持通用协同/反向差异。也就是说,IEnumerable<string>之类的内容与IEnumerable<object>不兼容。

C#4引入了静态检查定义网站安全通用协同/反差 - 但它也不会对你有所帮助。它要求通用参数仅用于输入或输出位置,但不能同时用于两者。也就是说,List<string>与C#4.0中的List<object>不兼容,但IEnumerable<string>可用作IEnumerable<object>,因为IEnumerable的类型参数仅用作Current属性的返回值(输出位置)。