能否使一个参数实现两个接口?

28

是否可能定义一个函数,该函数接受必须实现两个接口的参数?

(这两个接口只是我记起来的,不是我想要使用的接口)

private void DoSomthing(IComparable, ICollection input)
{

}

你可以使用与声明成员变量相同的技巧,不过这种方法需要实现类选择加入该模式。 - binki
4个回答

59
你可以:

1)定义一个继承两个必需接口的接口:

public interface ICombinedInterface : IComparable, ICollection {... }

private void DoSomething(ICombinedInterface input) {... }

2) 使用泛型:

private void DoSomething<T>(T input)
    where T : IComparable, ICollection
{...}

3
在VB.Net中:私有子程序 DoSomething(Of T As {IComparable, ICollection})(ByVal input As T) ... End Sub。 - Pondidum
这些解决方案中是否有一种比拥有两个单独的参数更有优势?直觉上似乎会很有用,但我很难想出一个具体的例子。 - CurtainDog
1
我现在想不出一个例子,但几天前我确实想做这件事。只传递一个参数比调用DoSomething(testData,testData)并传递相同的实例两次要更好看。 - Pondidum
10
  1. 只有在您可以更改实现两个接口的所有类以实现新接口时,该方法才有效。
  2. 我喜欢使用泛型的方式。
- Ian Ringrose

6
你可以从这两个接口中继承另一个接口,并使你的参数实现该接口。

2
只有在您可以更改实现两个接口的所有类以实现新接口时,它才能正常工作。 - Ian Ringrose
好的,并不是所有的都需要。只有你需要作为该方法参数使用的那些。 - Steve Willcock

3

是的,也不是。

正如Steve所建议的那样,您可以创建另一个第三方接口,其继承了您想要的两个接口,并将其用作参数类型。

然而,这也意味着使用的类还必须实现该第三个接口。

换句话说,以下操作将不起作用:

public interface I1 { }
public interface I2 { }
public class C : I1, I2 { }

public interface I3 : I1, I2 { }
public class YourClass
{
    public void Test(I3 i) { }
}

...
YourClass yc = new YourClass();
C c = new C();
yc.Test(c); // won't work, C does not implement I3

然而,你可以通过泛型的方式欺骗编译器,达到你想要的效果。

public class YourClass
{
    public void Test<T>(T i) where T: I1, I2 { }
}

现在它应该可以工作了。但我仍不确定这是否会引起其他问题,我需要考虑一下。


2
上述提到的通用函数方法是一个不错的方法,但有一个重要的限制:为了将对象强制转换为可以传递给具有多个通用约束的例程的类型,必须知道一个满足这些约束并且是被转换对象的父类型的类型。接受此类对象的例程将知道这样的类型(它作为通用类型参数传递),但没有很好的方法让类保留这样的信息并在以后使用它。如果多种不相关的类型都实现了IFoo和IBar,则设计一个能够接受多个不相关对象实例、将它们存储在列表或其他数据结构中,然后将所有项传递给具有通用IFoo+IBar参数的例程将会很困难。
如果可能需要这样的场景,最好的方法是为每个通用例程建立一个非通用的对应例程,该例程将接受例如IFoo类型的参数,并根据需要将其转换为IBar。然后可以将所有项存储在List中并将它们传递给该例程。虽然会失去通用方法的类型安全性,但有时无法实现完美的类型安全性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接