2009-07-28 69 views
5

我有一個通用的方法我可以將泛型方法限制爲多個接口嗎?

public static void DoSomething<T>() 
{...} 

。現在我想限制T.

public static void DoSomething<T>() where T: IInterface1 
{...} 

但我真正想要的是允許多個接口,像

public static void DoSomething<T>() where T: IInterface1, IInterface2 
{...} 

但是,這並不工作。編譯器說有點像

There's no implicit conversion from IInterface1 to IInterface2

There's no implicit conversion from IInterface2 to IInterface1

我想過讓類實現一個通用的接口,我可以參考但我沒有訪問類。

我有什麼可能允許多個接口?

感謝, 託比

編輯:這就是我想做的事。我正在開發一個Outlook-Add-In。我經常使用下面的這段代碼。

public static object GetItemMAPIProperty<T>(AddinExpress.MAPI.ADXMAPIStoreAccessor adxmapiStoreAccessor, object outlookItem, uint property) where T: Outlook.MailItem, Outlook.JournalItem 
    { 
     AddinExpress.MAPI.MapiItem mapiItem; 
     mapiItem = adxmapiStoreAccessor.GetMapiItem(((T)outlookItem)); 
     return mapiItem != null ? mapiItem.GetProperty(property) : null; 
    } 

的方法GetMapiItem需要一個對象,只要它是Outlook的項目(雜誌,郵件,聯繫人,...)之一。這就是爲什麼我限制T的原因。因爲它不能,比如說Outlook.MAPIFolder。

不,我已經改變了方法

public static object GetItemMAPIProperty<T>(AddinExpress.MAPI.ADXMAPIStoreAccessor adxmapiStoreAccessor, T outlookItem, uint property) 
    { 
     AddinExpress.MAPI.MapiItem mapiItem; 
     mapiItem = adxmapiStoreAccessor.GetMapiItem(((T)outlookItem)); 
     return mapiItem.GetProperty(property); 
    } 

但由於該方法GetMapiItem接受對象,開發人員(在這種情況下我)可以給它的任何類型。我希望這是有道理的。我不確定它是否適用於這個例子,但我想將一個泛型方法限制爲多個類型(使用OR)可能是一個好主意。

+0

你的目標是什麼框架,你是用Visual Studio編譯的,哪個版本?我在這裏VS 2008與.NET 3.5和上面的編譯就好了。你確定你給我們的例子就是你所擁有的。 – 2009-07-28 16:30:31

+1

,因爲那樣你說編譯器T應該是IInterface1和IInterface2而不是 – 2009-07-28 16:31:42

+0

他提供的代碼有效,他只需要說方法來獲取IInterface1或IInterface2的參數 – 2009-07-28 16:34:51

回答

1

一個方法是創建一個額外的接口延伸兩者接口1和2,然後你把這個接口,而不是其他2

這是做在Java中的一種方式;如果我沒有記錯,這應該在C#中工作以及#

希望有所幫助。

問候,TOBI還有:P

3

有無接口1和接口2都來自相同的基本接口派生。例如:

public static void DoSomething<T>() where T : ICommon 
    { 
     //... 
    } 

    public interface IInterface1 : ICommon 
    {} 

    public interface IInterface2 : ICommon 
    { } 

    public interface ICommon 
    { } 

做這種方式的好處是,你不必讓每次添加一個新的接口,從ICommon繼承時間更新DoSomething的()的定義。

編輯:如果你不能控制接口,你有幾個選項。這是你可以做的一件事...

protected static class DoSomethingServer<T1> where T1 : class 
    { 

     //Define your allowed types here 
     private static List<Type> AllowedTypes = new List<Type> { 
      typeof(IInterface1), 
      typeof(IInterface2) 
     }; 

     public static MethodInvoker DoSomething() 
     { 
      //Perform type check 
      if (AllowedTypes.Contains(typeof(T1))) 
      { 
       return DoSomethingImplementation; 
      } 
      else 
      { 
       throw new ApplicationException("Wrong Type"); 
      } 
     } 

     private static void DoSomethingImplementation() 
     { 
      //Actual DoSomething work here 
      //This is guaranteed to only be called if <T> is in the allowed type list 
     } 
    } 

使用這樣:

DoSomethingServer<IInterface1>.DoSomething(); 

不幸的是,這拿走編譯時類型安全,它只會在運行時炸燬如果你試圖在錯誤類型爲食。顯然這不太理想。

2

這對我來說編譯罰款:

interface I1 { int NumberOne { get; set; } } 
interface I2 { int NumberTwo { get; set; } } 

static void DoSomething<T>(T item) where T:I1,I2 
{ 
    Console.WriteLine(item.NumberOne); 
    Console.WriteLine(item.NumberTwo); 
} 

所以語法似乎罰款......也許它的其他東西是造成問題的原因。

1
public interface IInterfaceBase 
    { 

    } 
    public interface IInterface1 : IInterfaceBase 
    { 
     ... 
    } 
    public interface IInterface2 : IInterfaceBase 
    { 
     ... 
    } 

    public static void DoSomething<T>() where T: IInterfaceBase 
    { 
    } 

如果你想噸至是IInterface1或IInterface2使用上述

2

如果你的意思是該參數可以是I1的實現或I2的實現代碼,和他們無關的類型,那麼你不能寫一個方法組(即使用相同的方法名重載)來處理這兩種類型。

你甚至不能說(從納德借用!):

interface I1 { int NumberOne { get; set; } } 
    interface I2 { int NumberTwo { get; set; } } 

    static void DoSomething<T>(T item) where T : I1 
    { 
     Console.WriteLine(item.NumberOne); 
    } 

    static void DoSomething<T>(T item) where T : I2 
    { 
     Console.WriteLine(item.NumberTwo); 
    } 

    static void DoSomething<T>(T item) where T : I1, I2 
    { 
     Console.WriteLine(item.NumberOne); 
     Console.WriteLine(item.NumberTwo); 
    } 

這將使編譯器的方式來處理毫不​​含糊每一種可能性。但爲了幫助進行版本控制,C#試圖避免添加/刪除方法會改變其他方法的適用性的情況。

您需要編寫兩個不同名稱的方法來處理這兩個接口。

0

建立關於Earwicker所說的......姓名並非唯一的出路。你也可以改變方法簽名......

public interface I1 { int NumberOne { get; set; } } 
public interface I2 { int NumberTwo { get; set; } } 

public static class EitherInterface 
{ 
    public static void DoSomething<T>(I1 item) where T : I1 
    { 
     Console.WriteLine("I1 : {0}", item.NumberOne); 
    } 

    public static void DoSomething<T>(I2 item) where T : I2 
    { 
     Console.WriteLine("I2 : {0}", item.NumberTwo); 
    } 
} 

,當這樣的測試:

public class Class12 : I1, I2 
{ 
    public int NumberOne { get; set; } 
    public int NumberTwo { get; set; } 
} 

public class TestClass 
{ 
    public void Test1() 
    { 
     Class12 z = new Class12(); 
     EitherInterface.DoSomething<Class12>((I1)z); 
     EitherInterface.DoSomething<Class12>((I2)z); 
    } 
} 

此息率輸出:

I1 : 0 
I2 : 0 

這符合暴露一個方法的目標名稱給調用者,但不能幫助你,因爲你沒有使用參數。

相關問題