簡體   English   中英

約束通用類型參數的繼承

[英]Inheritance on a constrained generic type parameter

我知道不可能從泛型類型參數繼承,但是在為抽象類型的派生實現通用代理時會很方便的:-)

有人知道為什么這不可能嗎?

示例C#:

abstract class Foo
{
  public virtual void Bar()
  {
     // nop
  }
}

class FooProxy<TFoo> : TFoo
  where TFoo : Foo
{

  public override void Bar()
  {
    // do some stuff before
    base.Bar();
    // do some stuff after
  }

}

編輯:更多代碼來說明如何使用此示例。 考慮以下Foo的派生詞:

class FooX : Foo
{
  public string X { get; set; }
  public override void Bar()
  {
    Console.WriteLine("Doing Bar X");
  }
}

class FooY : Foo
{
  public string Y { get; set; }
  public override void Bar()
  {
    Console.WriteLine("Doing Bar Y");
  }
}

和調用代碼:

FooProxy<FooX> fooXProxy = new FooProxy<FooX>();
fooXProxy.X = "test X";
fooXProxy.Bar();

FooProxy<FooY> fooYProxy = new FooProxy<FooY>();
fooYProxy.Y = "test Y";
fooYProxy.Bar();

使用FooX和FooY時,將重用Bar()方法的FooProxy重寫中的代碼。

編輯:根據Pete OHanlon的答案進行了修改:使Bar()方法成為虛擬的。

因為你不能。 泛型不是模板。 您不應該像C ++模板那樣考慮它們,並且期望它們具有相同的行為。 它們是根本不同的概念。

C#規范明確禁止將類型參數用作基類:

C#3.0語言規范:類型參數(第4.5節)

類型參數不能直接用於聲明基類(第10.2.4節)或接口(第13.1.3節)。

更新:

我了解您想要做什么及其用途。 這是C ++模板的傳統用例。 具體來說,如果可以使用C#泛型來實現,那么Moq庫之類的東西就可以從中受益。 問題是,C ++模板是編譯時的“查找和替換”結構,而C#泛型是運行時的東西。

為了證明這一事實,對於本課程:

class Test<T> where T : class {
    // whatever contents it might have...
} 

僅單個IL將在編譯時被發射,並在運行時間,JIT編譯器將生成所有引用類型的類型參數的單個本地代碼。 這根本不像C ++模板,后者將為每個T分別發出本機代碼(這是經過優化的,但從概念上講,它們是完全獨立的代碼段)。

您不能從泛型類型參數繼承,因為類型在編譯時是未知的,因此編譯器無法弄清楚超類是什么。 我意識到,乍一看,編譯器可以弄清楚<T>是什么,這似乎表明它應該能夠弄清楚T是什么,但是兩者是不同的。

另外,您在Bar中遇到邏輯問題。 您不能調用base.Bar,因為這是抽象類型。 為了糾正此問題,您必須將Foo中的實現更改為

public virtual void Bar() {}

因為Foo是抽象類型。

如果您在類中實現了Foo,然后在模板中使用了Foo,則可以這樣做。

您也可以使用界面來執行您認為要執行的操作。

編輯:

仔細考慮一下您的代碼,這沒有任何意義。 您將需要創建GENERIC類型的基類,然后從該基類派生出來以實現您想要的工作。 這也將使地獄更加有意義...

abstract class Foo<T>  
{  
    public virtual void Bar();  
}

暫無
暫無

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

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