簡體   English   中英

在方法調用中處理多個泛型

[英]Dealing with multiple generics in a method call

最近,我一直在處理使用泛型的抽象類。 這一切都很好,因為我從這些類中獲得了很多實用程序,但是現在它正在編寫一些相當丑陋的代碼。 例如:

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而不必將其傳遞給泛型類的整個數組以使函數正常工作,但是我不想引用更高級別的類,因為有很多這樣的類。 我是我自己的聰明的受害者嗎?還是我還沒有考慮過一條途徑?

我想您的HelpMe方法將用於初始化具體的ClassBase<T>類型(基於約束的猜測)。 為了使代碼完全通用(如果在方法中的某個位置需要TC ),則可能需要同時保留兩個類型參數。

但是,您可以添加一個非通用基類,然后編寫如下代碼:

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

根據您的特定情況,這些方面的工作可能會使代碼更簡單一些。 但是,您需要修改基類以使其成為可能。

泛型確實有傳播代碼的趨勢,因此,很少將它們用作“ mixin”類。

Thomas提到了引入等效的非通用API的一種可能性。 我寧願重新設計,並盡可能使這些基類為非泛型的, 同時又要保持完整的類型安全性 是否實際可行取決於您的要求。

除了重新設計(或API復制)之外,還有另一種可能性: dynamic 如果您願意在助手方法中丟失IntelliSense(並且願意付出非常非常小的運行時性能損失),則可以在助手方法中使用dynamic

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 = ...;
        ...
    }
}

無需將其傳遞給泛型類的整個數組即可使函數正常工作

稍作更改可能會緩解這些問題。 將重復指定的類型移到類的泛型聲明。

  //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(); 
    } 
} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM