簡體   English   中英

對於C#,是否可以在泛型類的實例聲明中指定類型約束?

[英]For C#, is it possible to specify type constraints in an instance declaration of a generic class?

我想帶兩個具有共享層次結構的對象,它們都實現一個接口,並將它們放在一個容器中,例如List,它通常采用單個類型的參數。 我在這個問題中使用了非編譯代碼,因為我找不到C#的一個功能,它可以讓我在編譯時做我想問的事情。

所以,設置如:

public class DataObject
{
    int property;
}

public interface IWriteData
{
    void WriteData();
}

public class A : DataObject, IWriteData, IDoSomethingElseA
public class B : DataObject, IWriteData, IDoSomethingElseB

和代碼:

var x = new A();
var y = new B();
List<T> where T : (DataObject, IWriteData) mySharedContainer = new List<T>;
T.Add(x);
T.Add(y);

上面的列表聲明行不起作用,但是我能想到的最接近我的目標。 我的預感是,這不是目前能夠完成的事情,我需要:

  • 定義一個他們可以繼承的共享類,並且還實現了接口(在這種情況下我不想做,因為這不是我的代碼庫,我試圖盡可能減小占用空間)
  • 做運行時類型轉換,並失去編譯時類型檢查的好處
  • 通過編寫處理類型A的代碼和處理類型B的代碼來重復代碼。

但是,我會非常高興地發現其他情況。 在考慮它時,我看不出任何直接的理由,理論上,編譯器不能在該行說“好吧,從現在開始我將檢查添加到此列表的所有內容是否繼承自該類並實現這些接口“。

謝謝!

您想要的功能稱為交集類型 ,C#對交集類型的支持非常非常有限。 實際上只有一種方法可以指定類似的類型限制,它是這樣的:

class C 
{
    public static void M<T>(T t) where T : DataObject, IWriteData 
    {
        List<T> myList = new List<T>() { t };
        // With this restriction we can make both these conversions:
        IEnumerable<DataObject> iedo = myList; // Legal
        IEnumerable<IWriteData> iewd = myList; // Legal 
    }
}

T僅限於在實現IWriteData的類型和擴展DataObject的類型的 IWriteData的類型。

但這並不能解決你遇到的問題。 在這個解決方案中,我們可以調用M<A>M<B>並獲得T的列表,其中T絕對是DataObjectIWriteData 但你必須說出 T是什么。 T可以是AB ,但T不能是“ AB ”。 (並且“A或B”將是聯合類型 。)

在考慮它時,我看不出任何直接的理由,理論上,編譯器無法在該行說“好吧,從現在開始我將檢查添加到此列表的所有內容是否繼承自該對象類並實現這些接口“。

對象是類的實例;類擴展類,而不是對象。)

你是對的; 沒有理論上的理由。 有些語言支持union和intersection類型; Hack,我現在使用的語言,就是這樣一種語言。 TypeScript也支持這種類型的輸入。 但是C#不是其中之一,對不起。

這是不可能的。

在C#中,您只能為字段,方法,屬性等指定一種類型。這就是泛型無法執行此操作的原因。 泛型只是編譯為您使用的每種類型組合的單獨的類/方法。

您必須在類中實現接口或繼承接口,以便您只需指定一個接口。

我並不是百分之百地確定你想要達到的目的但是聲明

List<T> where T : (DataObject, IWriteData) mySharedContainer = new List<T>;

由於一些原因是不可能的。 首先,我們不能指定內聯泛型,如果我們可以, List<T>類型不接受兩個類型參數。

但是,正如我所看到的,你可以有效地創建另一個界面

public interface ISharedObject
{
    int Property { get; set; }

    void WriteData();
}

然后,您只需將您的類修改為:

public class A : DataObject, IWriteData, ISharedObject, IDoSomethingElseA
{
    public void WriteData();
}

public class B : DataObject, IWriteData, ISharedObject, IDoSomethingElseB
{
    public void WriteData();
}

因此,接口ISharedObject同時具有PropertyWriteData()簽名。 DataObject實現了Property (注意我將其更改為屬性而不是字段)。 然后接口IWriteData定義WriteData方法的契約。 因此兩者都會編譯。

現在你有一個類型的參數,可以調用

var x = new A();
var y = new B();
var list = new List<ISharedObject>();
list.Add(x);
list.Add(y);

如果我誤解了您的要求,請事先提前申請。

暫無
暫無

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

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