将无约束泛型类型参数传递给约束方法

时间:2015-02-04 20:48:00

标签: c# generics type-constraints

我也有方法:

public TValueType? DoStuffWithValueType<TValueType>(int x, int y) 
   where TValueType: struct {}

public TRefType DoStuffWithRefType<TRefType>(int x, int y) 
   where TRefType: class {} 

我如何用新的第三种方法包装它们?

以下是没有编译的,因为我无法说服编译器T在调用DoStuffWithValueType时实际上是一个结构:

public T DoStuff<T>(int x, int y) {

   if(typeof(T).IsValueType)
   {
      return DoStuffWithValueType<T>(x, y);
   }

   return DoStuffWithRefType<T>(x, y);
}

我已经尝试重载DoStuff,但是这次尝试失败了,因为泛型约束不是方法签名的一部分。
我也试图摆脱约束,但我不能。

有什么想法吗?谢谢!

2 个答案:

答案 0 :(得分:2)

基本上你不能用反射来调用相关的方法,这很难看。

当然,您可以使用动态类型来执行此操作,这会隐藏您的反射:

public T DoStuff<T>(int x, int y) {
   dynamic d = this;
   if(typeof(T).IsValueType)
   {
       return d.DoStuffWithValueType<T>(x, y);
   }    
   return d.DoStuffWithRefType<T>(x, y);
}

您可能认为比使用反射手动更清洁 - 或者您可能不会:)

我不知道如何使编译器和#34;信任&#34;一个类型参数,它通常不会这样做。

答案 1 :(得分:1)

除了Jon Skeet使用dynamic之外,我能想到的最简洁的方法,最小化所需的反射,以及尽可能多地通过编译器验证,是通过辅助类调用该方法。

abstract class DoStuffHelper<T> {
    public abstract T DoStuff(int x, int y);
}

class DoStuffWithValueTypeHelper<T> : DoStuffHelper<T> where T : struct {
    public override T DoStuff(int x, int y) {
        return DoStuffWithValueType<T>(x, y);
    }
}

class DoStuffWithRefTypeHelper<T> : DoStuffHelper<T> where T : class {
    public override T DoStuff(int x, int y) {
        return DoStuffWithRefType<T>(x, y);
    }
}

public T DoStuff<T>(int x, int y) {
   DoStuffHelper<T> helper;
   Type helperType;

   if(typeof(T).IsValueType)
       helperType = typeof(DoStuffWithValueTypeHelper<>);
   else
       helperType = typeof(DoStuffWithRefTypeHelper<>);

   helperType = helperType.MakeGenericType(typeof(T));
   helper = (DoStuffHelper<T>)Activator.CreateInstance(helperType);

   return helper.DoStuff(x, y);
}

如果适合您的情况,您可以在Dictionary<Type, object>中缓存帮助程序类,以避免每次都重新创建它们。