C# 我可以将泛型方法限制为多个接口吗?

C# 我可以将泛型方法限制为多个接口吗?,c#,generics,where,C#,Generics,Where,我有一个通用方法 public static void DoSomething<T>() {...} publicstaticvoiddosomething() {...} 。现在我想限制T public static void DoSomething<T>() where T: IInterface1 {...} publicstaticvoiddosomething(),其中T:IInterface1 {...} 但我真正想要的是允许多个接口,比如 publi

我有一个通用方法

public static void DoSomething<T>()
{...}
publicstaticvoiddosomething()
{...}
。现在我想限制T

public static void DoSomething<T>() where T: IInterface1
{...}
publicstaticvoiddosomething(),其中T:IInterface1
{...}
但我真正想要的是允许多个接口,比如

public static void DoSomething<T>() where T: IInterface1, IInterface2
{...}
publicstaticvoiddosomething(),其中T:IInterface1,IInterface2
{...}
但这不起作用。编译器说的是

public static void DoSomething<T>() where T: IInterface1, IInterface2
{...}
没有从IInterface1到IInterface2的隐式转换

没有从IInterface2到IInterface1的隐式转换

我想让这些类实现一个我可以参考的公共接口,但我没有访问这些类的权限

我有什么可能允许多个接口

谢谢, 托比

编辑:以下是我想做的。我正在开发Outlook加载项。我经常使用下面的这段代码

    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;
    }
public静态对象getItemMapProperty(AddinExpress.MAPI.ADXMAPIStoreAccessor ADXMAPIStoreAccessor,object outlookItem,uint属性),其中T:Outlook.MailItem,Outlook.JournalItem
{
AddinExpress.MAPI.MapiItem MapItem;
mapiItem=adxmapiStoreAccessor.GetMapiItem(((T)outlookItem));
返回mapiItem!=null?mapiItem.GetProperty(属性):null;
}
只要对象是Outlook的项目之一(日记、邮件、联系人等),GetMapiItem方法就会接受该对象。这就是我限制T的原因。因为它不能是Outlook.Mapi文件夹

不,我已将方法更改为

    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);
    }
公共静态对象GetItemMapProperty(AddinExpress.MAPI.ADXMAPIStoreAccessor ADXMAPIStoreAccessor、T outlookItem、uint属性)
{
AddinExpress.MAPI.MapiItem MapItem;
mapiItem=adxmapiStoreAccessor.GetMapiItem(((T)outlookItem));
返回MapItem.GetProperty(属性);
}

但是开发人员(在本例中为I)可以为其提供任何类型,因为方法GetMapiItem接受对象。我希望这是有道理的。我不确定它是否适用于该示例,但我想将泛型方法限制为多个类型(使用或)可能是个好主意。

一种方法是创建一个额外的接口,扩展Interface1和Interface2。然后你把这个接口,而不是另外2个

这是用java实现的一种方法;如果我没记错的话,这在C语言中也应该可以使用#

希望有帮助


关于tobi:p

的Interface1和Interface2都来自同一个基本接口。例:

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

    public interface IInterface1 : ICommon
    {}

    public interface IInterface2 : ICommon
    { }

    public interface ICommon
    { }
publicstaticvoiddosomething(),其中T:ICommon
{
//...
}
公共接口界面1:ICommon
{}
公共接口界面2:ICommon
{ }
公共接口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,其中T1:class
{
//在此处定义允许的类型
私有静态列表AllowedTypes=新列表{
类型(界面1),
类型(界面2)
};
公共静态MethodInvoker DoSomething()
{
//执行类型检查
if(AllowedTypes.Contains(typeof(T1)))
{
返回剂量;实施;
}
其他的
{
抛出新的ApplicationException(“错误类型”);
}
}
私有静态void DoSomethingImplementation()
{
//实际剂量在这里起作用
//保证仅当在允许的类型列表中时才调用此函数
}
}
用作:

DoSomethingServer<IInterface1>.DoSomething();
DoSomethingServer.DoSomething();

不幸的是,这会破坏编译时类型的安全性,只有在尝试输入错误的类型时,它才会在运行时崩溃。显然这不太理想。

这对我来说很好:

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);
}
interface I1{int NumberOne{get;set;}
接口I2{int NumberTwo{get;set;}}
静态空隙剂量测量(T项),其中T:I1,I2
{
控制台写入线(项目编号);
控制台写入线(项目编号WO);
}
所以语法看起来很好。。。可能是其他原因造成了这个问题。

public interfacebase接口
    public interface IInterfaceBase
    {

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

    public static void DoSomething<T>() where T: IInterfaceBase
    {
    }
{ } 公共接口IInterface1:IInterfaceBase { ... } 公共接口IInterface2:IInterfaceBase { ... } 公共静态void DoSomething(),其中T:IInterfaceBase { }

如果您希望T是IIinterface1或IIinterface2,请使用上面的代码

如果您的意思是参数可以是I1的实现或I2的实现,并且它们是不相关的类型,那么您不能编写一个方法组(即具有相同方法名称的重载)来处理这两种类型

你甚至不能说(向良信电器借来!):

interface I1{int NumberOne{get;set;}
接口I2{int NumberTwo{get;set;}}
静态空隙剂量仪(T项),其中T:I1
{
控制台写入线(项目编号);
}
静态空隙剂量仪(T项),其中T:I2
{
控制台写入线(项目编号WO);
}
静态空隙剂量测量(T项),其中T:I1,I2
{
控制台写入线(项目编号);
控制台写入线(项目编号WO);
}
这将为编译器提供一种无歧义地处理各种可能性的方法。但是为了帮助进行版本控制,C#试图避免添加/删除一个方法会改变另一个方法的适用性的情况


您需要编写两个名称不同的方法来处理这两个接口。

以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