2009-07-28 68 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 

这符合暴露一个方法的目标名称给调用者,但不能帮助你,因为你没有使用参数。

相关问题