使用通用型无约束通过与约束泛型类型 [英] Using a generic type passed without constraint with a constrained generic type

查看:122
本文介绍了使用通用型无约束通过与约束泛型类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有以下类:

public interface IFrobnicator<T> { }

class ComparableFrobnicator<T> : IFrobnicator<T> where T : IComparable<T>
{
    public ComparableFrobnicator(T value) { }
}

class EquatableFrobnicator<T> : IFrobnicator<T> where T : IEquatable<T>
{
    public EquatableFrobnicator(T value) { }
}

你可以写方法

public IFrobnicator<T> MakeFrobnicatorFromComparable<T>(T value) where T : IComparable<T>
{
    return new ComparableFrobnicator<T>(value);
}

public IFrobnicator<T> MakeFrobnicatorFromEquatable<T>(T value) where T : IEquatable<T>
{
    return new EquatableFrobnicator<T>(value);
}

如果我想将它统一到一个单一的方法, 't compile:

If I wanted to unify that into a single method, the most obvious way won't compile:

public IFrobnicator<T> MakeFrobnicator<T>(T value)
{
    if (value is IComparable<T>)
    {
        return new ComparableFrobnicator<T>(value);
    }
    else if (value is IEquatable<T>)
    {
        return new EquatableFrobnicator<T>(value);
    }
    else throw new ArgumentException();
}

编译时出现以下错误:

CS0314类型'T'不能用作通用类型或方法'UserQuery.ComparableFrobnicator'中的类型参数'T'。没有从T到System.IComparable的换档或类型参数转换。

CS0314 The type 'T' cannot be used as type parameter 'T' in the generic type or method 'UserQuery.ComparableFrobnicator'. There is no boxing conversion or type parameter conversion from 'T' to 'System.IComparable'.

c $ c> new ComparableFrobnicator< T> 与新ComparableFrobnicator< IComparable< T> 因为这会导致问题, code> value 退出 - 您无法从接口类型转换为具体类型。

I can't replace new ComparableFrobnicator <T> with new ComparableFrobnicator<IComparable<T>> because that causes problems down the line with getting value back out - you cannot cast from an interface type to a concrete type.

的反射:

public IFrobnicator<T> MakeFrobnicator<T>(T value)
{
    if (value is IComparable<T>)
    {
        var constructor = typeof(ComparableFrobnicator<>).MakeGenericType(typeof(T)).GetConstructor(new[] { typeof(T) });
        return (IFrobnicator<T>)constructor.Invoke(new object[] { value});
    }
    else if (value is IEquatable<T>)
    {
        var constructor = typeof(EquatableFrobnicator<>).MakeGenericType(typeof(T)).GetConstructor(new[] { typeof(T) });
        return (IFrobnicator<T>)constructor.Invoke(new object[] { value });
    }
    else throw new ArgumentException();
}

这似乎完美,但看起来像一个语言的倒退这种强大的类型推理,我习惯。

That seems to work perfectly, but looks like a step backwards in a language with such powerful type inference as I'm used to. Is there something I'm missing, or a better technique I missed?

推荐答案

尝试扩展方法,
方法 value.MakeFrobnicator()实施有助于解决泛型类型params问题

Try the extention methods approach, The way value.MakeFrobnicator() is implemented helps to resolve generic type params issue

public interface IFrobnicator<T> { }

public class ComparableFrobnicator<T> :IFrobnicator<T> 
                              where T  :IComparable<T> 
 {
    public ComparableFrobnicator(T param) { }
 }

public class EquatableFrobnicator<T> :IFrobnicator<T>
                              where T : IEquatable<T> 
{
   public EquatableFrobnicator(T value) { }
}

 public static class FrobnicatorExtentions
 {
    public static IFrobnicator<T> 
          MakeFrobnicatorFromComparable<T>(this T value)
    where T: IComparable<T>
    {                                                            
      //return new ComparableFrobnicator<T>(value);      
     return value.MakeFrobnicator();
    }

    public static IFrobnicator<T> 
           MakeFrobnicatorFromEquatable<T>(this T value)
    where T : IEquatable<T>
    {
      // return new EquatableFrobnicator<T>(value);
     return value.MakeFrobnicator();
    }  

    public static IFrobnicator<T> 
                  MakeFrobnicator<T>(this IEquatable<T> value) 
    where T: IEquatable<T>
    {
      if (value is T)
      {
        if (value is IEquatable<T>)
        {
          return new EquatableFrobnicator<T>((T)value);
        } 
      }

     throw new InvalidCastException();
    }

   public static IFrobnicator<T> 
                 MakeFrobnicator<T>(this IComparable<T> value) 
   where T : IComparable<T>
  {
     if (value is T)
     {
       if (value is IComparable<T>)
       {
         return new ComparableFrobnicator<T>((T)value);
      }
     }

    throw new InvalidCastException();
  }

}

这篇关于使用通用型无约束通过与约束泛型类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆