我有一个通用的方法
public static void DoSomething<T>()
{...}
。现在我想限制那个T.
public static void DoSomething<T>() where T: IInterface1
{...}
但我真正想要的是允许多个接口,比如
public static void DoSomething<T>() where T: IInterface1, IInterface2
{...}
但这不起作用。编译器说类似
没有从IInterface1到IInterface2的隐式转换
没有从IInterface2到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的一个项目(Journal,Mail,Contact,...)。这就是为什么我限制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);
}
但是开发人员(在本例中为I)可以为其提供任何类型,因为GetMapiItem方法接受一个对象。我希望这是有道理的。我不确定它是否适用于该示例,但我认为将泛型方法限制为多个类型(使用OR)可能是一个好主意。
答案 0 :(得分:3)
让Interface1和Interface2都来自相同的基本接口。例如:
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();
不幸的是,这会消除编译时类型的安全性,如果尝试输入错误的类型,它只会在运行时爆炸。显然这不太理想。
答案 1 :(得分:3)
这对我来说很好:
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);
}
所以语法看起来很好......也许是引起问题的其他因素。
答案 2 :(得分:2)
如果您的意思是参数可以是I1的实现或I2的实现,并且它们是不相关的类型,那么您不能编写一个方法组(即具有相同方法名称的重载)来处理这两种类型。 / p>
你甚至不能说(从nader借来!):
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#试图避免添加/删除方法会改变另一种方法的适用性的情况。
您需要编写两个具有不同名称的方法来处理这两个接口。
答案 3 :(得分:1)
一种方法是创建一个扩展Interface1和2的附加接口。然后你把这个接口而不是其他2接口。
这是在java中执行此操作的一种方法;如果我没记错的话,这应该也适用于C#
希望有所帮助。问候,tobi:P
答案 4 :(得分:1)
public interface IInterfaceBase
{
}
public interface IInterface1 : IInterfaceBase
{
...
}
public interface IInterface2 : IInterfaceBase
{
...
}
public static void DoSomething<T>() where T: IInterfaceBase
{
}
如果您希望T为IInterface1或IInterface2,请使用上面的代码
答案 5 :(得分: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
这符合向调用者公开单个方法名称的目标,但由于您没有使用参数,因此无法帮助您。