簡體   English   中英

帶通用參數的接口與帶通用方法的接口

[英]Interface with generic parameter vs Interface with generic methods

假設我有這樣的界面和具體的實現

public interface IMyInterface<T>
{
    T My();
}

public class MyConcrete : IMyInterface<string>
{
    public string My()
    {
        return string.Empty;
    }
}

因此,我為strings創建MyConcrete實現,可以為int提供一個更具體的實現。 沒關系。 但是,假設我想做同樣的事情,但是要使用通用方法,所以我有

public interface IMyInterface2
{
    T My<T>();
}

public class MyConcrete2 : IMyInterface2
{
    public string My<string>()
    {
        throw new NotImplementedException();
    }
}

因此,我具有相同的IMyInterface2 ,但它通過T My<T>()定義了通用行為。 在我的具體課程中,我想實現My行為,但對於具體的數據類型為string 但是C#不允許我這樣做。

我的問題是為什么我不能這樣做? 換句話說,如果我可以將MyInterface<T>創建為MyClass : MyInterface<string>並在此時停止泛型,那么為什么不能使用泛型方法T My<T>()來做到這一點?

您的通用方法實現也必須是通用的,因此必須是:

public class MyConcrete2 : IMyInterface2
{
    public T My<T>()
    {
        throw new NotImplementedException();
    }
}

為什么在這里不能執行My<string>() 因為接口協定需要一個方法,所以可以使用任何類型參數T調用該方法,而您必須履行該協定。

為什么在這一點上不能停止通用性 因為這會導致如下情況:

類聲明:

public interface IMyInterface2
{
    T My<T>(T value);
}

public class MyClass21 : IMyInterface2
{
    public string My<string>(string value) { return value; }
}

public class MyClass22 : IMyInterface2
{
    public int My<int>(int value) { return value; }
}

用法:

var item1 = new MyClass21();
var item2 = new MyClass22();

// they both implement IMyInterface2, so we can put them into list
var list = new List<IMyInterface2>();
list.Add(item1);
list.Add(item2);

// iterate the list and call My method
foreach(IMyInterface2 item in list)
{
    // item is IMyInterface2, so we have My<T>() method. Choose T to be int and call with value 2:
    item.My<int>(2);

    // how would it work with item1, which has My<string> implemented?
}

因為您的接口聲明了泛型方法T My<T>() ,但是您的實現並未實現具有該特定簽名的函數。

為了實現所需的功能,需要在第一個示例中向接口提供T泛型參數:

public interface IMyInterface2<T>
{
        T My();
}

public class MyConcrete2 : IMyInterface2<string>
{
    public string My()
    {
        throw new NotImplementedException();
    }
}

當您編寫通用方法時,定義用於保留占位符。 當您調用該方法時,實際類型就會出現。 所以你應該寫

public T My<T>()
{
    throw new NotImplementedException();
}

當您調用該方法時,可以在其中使用字符串。

您的解決方案無法正常工作有兩個原因。

首先,接口是合同。 當實現IMyInterface2您保證將實現一個名為My的函數,該函數采用通用類型參數並返回該類型。 MyConcrete2不執行此操作。

其次,C#泛型不允許任何類型的類型參數專門化。 (我希望C#支持這一點。)這在C ++模板中很常見,您的示例將在該模板中編譯,但是如果MyConcrete2任何用法如果不使用string調用My都將無法編譯。

暫無
暫無

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

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