代码之家  ›  专栏  ›  技术社区  ›  thaBadDawg

在方法调用中处理多个泛型

  •  0
  • thaBadDawg  · 技术社区  · 14 年前

    最近我经常处理使用泛型的抽象类。这一切都很好也很好,因为我从这些类中得到了很多实用程序,但是现在它正在为一些相当难看的代码做准备。例如:

    abstract class ClassBase<T>
    {
        T Property { get; set; }
    }
    
    class MyClass : ClassBase<string>
    {
        OtherClass PropertyDetail { get; set; }
    }
    

    这个实现并没有那么疯狂,除非我想引用助手类中的抽象类,然后我必须列出一个泛型列表,以便引用实现的类,如下所示。

    class Helper
    {
        void HelpMe<C, T>(object Value)
            where C : ClassBase<T>, new()
        {
            DoWork();
        }
    }
    

    这只是一个简单的例子,因为我有一些方法调用,其中WHERE子句的列表以5或6行的长度结束,以处理所有的通用数据。我真正想做的是

    class Helper
    {
        void HelpMe<C>(object Value)
            where C : ClassBase, new()
        {
            DoWork();
        }
    }
    

    但它显然不会编译。我想引用ClassBase而不必为函数传递一个完整的泛型类数组,但是我不想引用更高级的类,因为有很多类。我是自己聪明才智的牺牲品,还是有一条我还没有考虑过的路?

    3 回复  |  直到 14 年前
        1
  •  2
  •   Tomas Petricek    14 年前

    我想你的 HelpMe 方法将用于初始化具体的 ClassBase<T> 类型(基于约束的猜测)。保持代码完全通用(如果您需要两者 T C 在方法的某个地方),您可能需要保留这两个类型参数。

    但是,可以添加非泛型基类,然后编写如下内容:

    abstract class ClassBase { 
       object UntypedProperty { get; set; } 
    } 
    abstract class ClassBase<T> : ClassBase { 
       T Property { get; set; } 
       public override object UntypedProperty { 
         get { return Property; }
         set { Property = (T)value; }
       }
    } 
    

    然后您可以这样编写helper方法:

    void HelpMe<C>(object Value) where C : ClassBase, new() { 
      var n = new C();
      c.UntypedProperty = Value;
    } 
    

    根据您的具体场景,这些行中的某些内容可能会起作用,并使代码稍微简单一些。但是,您需要修改基类以使这成为可能。

        2
  •  0
  •   Stephen Cleary    14 年前

    泛型确实倾向于通过代码来传播,因此它们被自己用作“混合”类。

    托马斯提到了引入等效非泛型API的一种可能性。如果可能的话,我希望重新设计并使这些基类非泛型 同时保持全型安全 . 这是否实际可行取决于您的需求。

    除了重新设计(或API复制)之外,还有一种可能: 动态 . 如果您愿意在助手方法中丢失IntelliSense(并且愿意支付非常非常非常小的运行时性能惩罚),则可以使用 动态 在帮助程序方法中:

    class Helper
    {
        void HelpMe<C>(object Value)
          //  where C : ClassBase<T>, new() // no longer needed, but should be documented
        {
            dynamic cObj = Activator.CreateInstance<C>(); // instead of "new C()"
            cObj.PropertyDetail = ...;
            cObj.Property = ...;
            ...
        }
    }
    
        3
  •  0
  •   Amy B    14 年前

    无需传递一整组泛型类就可以使函数正常工作。

    一个小的变化可能会缓解这些呼叫。将重复指定的类型移到类的泛型声明中。

      //before
    Helper x = new Helper();
    x.HelpMe<MyClass, string>(x);
    x.HelpMe<MyClass, string>(y);
    
      //after
    Helper x = new Helper<string>();
    x.HelpMe<MyClass>(x);
    x.HelpMe<MyClass>(y);
    
    
    
      //the change
    class Helper<T>
    { 
        void HelpMe<C>(object Value) 
            where C : ClassBase<T>, new() 
        { 
            DoWork(); 
        } 
    }