2010-07-25 29 views
5

我基本上希望做的是設計一個通用接口,該接口在實現時會生成一個類似T的類,除了它具有一些附加功能。下面是什麼我談論的例子:C#接口:是否可以引用在接口本身內實現接口的類型?

public interface ICoolInterface<T> 
{ 
    T Value { get; set; } 
    T DoSomethingCool(); 
} 

public class CoolInt : ICoolInterface<int> 
{ 
    private int _value; 

    public CoolInt(int value) 
    { 
     _value = value; 
    } 

    public int Value 
    { 
     get { return _value; } 
     set { _value = value; } 
    } 

    public int DoSomethingCool() 
    { 
     return _value * _value; 
     // Ok, so that wasn't THAT cool 
    } 
} 

這是一個好主意,但爲了使用CoolInt,我需要做這樣的事情:

CoolInt myCoolInt = new CoolInt(5); 
int myInt = myCoolInt.Value; 

我至少在分配方面,CoolInt的工作原理與int相同。換句話說:

CoolInt myCoolInt = 5; 
int myInt = myCoolInt; 

要做到這一點,我添加了這兩個轉換操作符來我CoolInt類:

public static implicit operator CoolInt(int val) 
    { 
     return new CoolInt(val); 
    } 

    public static implicit operator int(CoolInt obj) 
    { 
     return obj.Value; 
    } 

工程赫然。現在,如果我可以將這兩個過載添加到接口,我更喜歡它,以便接口的實施者強制來實現這些操作符。問題是,這些操作員的原型直接指向CoolInt。

對於隱式定義或尚未定義的事物,C#有很多「佔位符」名稱。常規編程中常用的T就是一個例子。我想在Properties中使用的value關鍵字是另一個關鍵字。這個「參考」可以被認爲是另一個參考。我希望我的界面中可以使用另一個符號來表示「正在實現此界面的類的類型」,例如, 「實施者」。

public static implicit operator implementer(int val) 
    { 
     return new IntVal(val); 
    } 

    public static implicit operator int(implementer obj) 
    { 
     return obj.Value; 
    } 

這可能嗎?

回答

2

可悲的是沒有:(

C使用時涉及到運算符重載#做得不好(這是一個例子,一個是對某些運營商類型通用約束)。

+0

是的,運算符重載有時不起作用,這很奇怪:在我發佈在這裏的抽象通用示例中,它似乎只能以一種方式工作,而不能以另一種方式工作! – 2010-07-25 19:41:26

4

你爲什麼不創建一個abstract class?這樣你就可以在你的課堂上建立一些「默認」功能。

+1

我認爲這會讓我成爲那裏的一部分,但我認爲我仍然會遇到問題。假設我有AbstractCoolClass,並且具體版本被稱爲CoolInt,如前所述。 那麼,從int到CoolInt的隱式轉換運算符將返回一個AbstractCoolClass引用,然後該引用將不得不明確轉換爲CoolInt。 我寧願沒有明確的演員,但看起來我可能別無選擇! – 2010-07-25 18:15:51

+0

抽象*泛型*類不需要返回'AbstractCoolClass'對象,它可以返回'T'。 – 2010-07-25 19:11:19

+0

我需要兩種方式進行轉換。所以,我需要一個接受'T'的運算符並返回我的類的實例,另一個方法接受我的類的實例並返回一個'T'。 在這兩種情況下,我都需要使用'AbstractCoolClass'作爲我的類的實例的數據類型。在後一種情況下,這不是問題,因爲我可以簡單地將重載方法從'AbstractCoolClass'轉換爲具體類(例如'CoolInt')。 但是,在前一種情況下,我必須返回一個'AbstractCoolClass',這取決於客戶端開發人員進行強制轉換。 – 2010-07-25 19:48:43

0

爲什麼不使用擴展方法,而不是?那就讓你「增加」的方法來int,而不必使用不同的類型。

0

這可能是你可以使用一個抽象基類最接近的,但可悲的是,即使這有一個問題與隱運營商之一,你必須這樣做: -

 CoolInt x = (CoolInt)5; 
     int j = x; 

夠了嗎?

// Slightly sneaky, we pass both the wrapped class and the wrapping class as type parameters to the generic class 
    // allowing it to create instances of either as necessary. 

    public abstract class CoolClass<T, U> 
     where U : CoolClass<T, U>, new() 
    { 
     public T Value { get; private set; } 

     public abstract T DoSomethingCool(); 

     // Non-public constructor 
     protected CoolClass() 
     { 
     } 

     public CoolClass(T value) 
     { 
      Value = value; 
     } 

     public static implicit operator CoolClass<T, U>(T val) 
     { 
      return new U() { Value = val}; 
     } 

     public static implicit operator T(CoolClass<T, U> obj) 
     { 
      return obj.Value; 
     } 

    } 

    public class CoolInt : CoolClass<int, CoolInt> 
    { 
     public CoolInt() 
     { 
     } 

     public CoolInt(int val) 
      : base(val) 
     { 
     } 

     public override int DoSomethingCool() 
     { 
      return this.Value * this.Value; // Ok, so that wasn't THAT cool 
     } 
    } 
0

如果至少對於接口來說可以聲明一個類按照對象實現一個接口將是有幫助的;如果存在「接口」泛型類型約束,這將特別酷。那麼可以,例如,像做(VB語法)

 
Class Foo(Of T as Interface) 
    Implements T via Bar ' Declares variable 'bar' of type T 
    Sub DoSomething 
    ' Does something 
    End Sub 
End Class 

再投一個Foo(的T)爲T和有它像一個T.也許從MS有人能的想法絆倒並傳遞它?

我應該注意到,順便說一句,類似於您ICoolInterface一個很好的模式:

 
public interface ISelf<T> 
{ 
    T Self { get;} 
} 
public interface IFoozle 
{ 
    ... definitions for IFoozle 
} 
public interface IFoozle<T> : ISelf<T> , IFoozle; 
{ 
    /* Empty except for above declarations */ 
} 
... similarly define IWoozle and IWoozle<T> etc. 

然後一個可以聲明能夠實現IWoozle和IFoozle一個領域,從BoozleBase繼承(實現兩者都不是),通過:

 
    IWoozle<IFoozle<BoozleBase>> myField1; 
or 
    IFoozle<IWoozle<BoozleBase>> myField2; 

請注意,上述兩種類型可以相互轉換,也可以轉換爲也包含其他接口的類型。如果只需要將滿足多個約束的變量傳遞給方法,則可以通過使用通用方法更容易地獲得這樣的事物。不幸的是,沒有辦法在一個字段中存儲一個未知類型的對象,這樣它就可以被傳遞給具有多個約束的通用函數。