如何在界面中使用不同的模板参数两次使用相同的界面?

我认为这个例子会更清楚。 我们希望在处理器类中看到两种具有不同参数的方法。 “int Process(int value);” “双重过程(双重价值);”

但是编译器说IR91:’Generics.IRoot’不能同时实现’Generics.IProcess’和’Generics.IProcess’,因为它们可能统一了某些类型参数替换。

public class Processor : IRoot { // Here we want 2 methods public int Process(int item) { } public double Process(double item) { } } public interface IProcess { TResult Process(TItem item); } public interface IRoot : IProcess, IProcess { } 

你可能会使用这种实现。 你会失去一些通用的论点:

 public interface IBase where TM : bType where TPkey : new () { TM Get(TPkey key); } public interface IABase : IBase {} public interface IBBase : IBase {} public class Root  : IABase, IBBase where TM : MType where TPM : PMType where TPK : new() { ConcreteTmA IABase.Get(TPK key) { } ConcreteTmB IBBase.Get(TPK key) { } } 

因此,在发布我对该问题的第一个答案(#1)之后 ,我意识到人们通常可能希望能够将差异化接口的值转换为非差异化接口。 换句话说,人们想要做以下事情

 IProcessWithDifferentiator : IProcess 

但我们不能,因为在使用界面时我们会遇到同样的错误(类型可能会统一)。

我注意到OP没有具体要求这个,但可以看出它将是下一个逻辑场景。

所以,回到绘图板,并返回一个丑陋的解决方案,这是一个方法返回下转换类型,和代理,以支持这种方法的构造。 (丑陋的唯一缓解是代理类可以在某种程度上重复使用,如下所示。)以下是此练习的结果。

 public interface Second { } public interface Third { } public class Processor : IRoot { // Here we want 3 methods public float Process ( float item ) { System.Console.WriteLine ( " ...float Process..." ); return (float) (item - 55.75); } public int Process ( int item ) { System.Console.WriteLine ( " ...int Process..." ); return item + 1; } public double Process ( double item ) { System.Console.WriteLine ( " ...double Process..." ); return item + 10.748; } IProcess IProcessWithDifferentiator.ConvertToBase () { return new TP_Proxy ( this ); } IProcess IProcessWithDifferentiator.ConvertToBase () { return new TP_Proxy ( this ); } } public class TestProcessor : IRoot { int IProcess.Process ( int item ) { System.Console.WriteLine ( " ...int Process1..." ); return item - 11; } int IProcessWithDifferentiator.Process ( int item ) { System.Console.WriteLine ( " ...int Process2..." ); return item + 12; } int IProcessWithDifferentiator.Process ( int item ) { System.Console.WriteLine ( " ...int Process3..." ); return item + 100302; } IProcess IProcessWithDifferentiator.ConvertToBase () { return new TP_Proxy ( this ); } IProcess IProcessWithDifferentiator.ConvertToBase () { return new TP_Proxy ( this ); } } public interface IProcess { TResult Process ( TItem item ); } public interface IProcessWithDifferentiator // would love to ": IProcess" here but won't work above { TResult Process ( TItem item ); // replicated method from IProcess... yuck(!) IProcess ConvertToBase (); } // Having a proxy sucks. But at least this proxy is shared among multiple classes implementing the IProcess concept. class TP_Proxy : IProcess { public TP_Proxy ( IProcessWithDifferentiator px ) { _proxyTo = px; } private IProcessWithDifferentiator _proxyTo; TResult IProcess.Process ( TItem item ) { return _proxyTo.Process ( item ); } } public interface IRoot : IProcess, IProcessWithDifferentiator, IProcessWithDifferentiator { } class Program { static void Main ( string [] args ) { Processor p = new Processor (); // Direct conversion of first one, of course IProcess a1 = p; System.Console.WriteLine ( "a1 .Process(3.3) = " + a1.Process ( (float) 3.3 ) ); // Conversion of differentiated class IProcessWithDifferentiator a2 = ((IProcessWithDifferentiator) p); System.Console.WriteLine ( "a2d.Process(4) = " + a2.Process ( 4 ) ); IProcessWithDifferentiator a3 = (IProcessWithDifferentiator) p; System.Console.WriteLine ( "a3d.Process(5.5) = " + a3.Process ( 5.5 ) ); // Conversions to undifferentiated class using ugly proxies IProcess a2u = ((IProcessWithDifferentiator) p).ConvertToBase (); System.Console.WriteLine ( "a2u.Process(4) = " + a2u.Process ( 4 ) ); IProcess a3u = ((IProcessWithDifferentiator) p).ConvertToBase (); System.Console.WriteLine ( "a3u.Process(5.5) = " + a3u.Process ( 5.5 ) ); TestProcessor q = new TestProcessor (); IProcess b1 = q; // Direct conversion of first one, of course System.Console.WriteLine ( "b1 .Process(3) = " + b1.Process ( 3 ) ); // Conversion of differentiated class IProcessWithDifferentiator b2d = (IProcessWithDifferentiator) q; System.Console.WriteLine ( "b2d.Process(4) = " + b2d.Process ( 4 ) ); IProcessWithDifferentiator b3d = (IProcessWithDifferentiator) q; System.Console.WriteLine ( "b3d.Process(5) = " + b3d.Process ( 5 ) ); // Conversions to undifferentiated class using ugly proxies IProcess b2u = ((IProcessWithDifferentiator) q).ConvertToBase (); System.Console.WriteLine ( "b2u.Process(4) = " + b2u.Process ( 4 ) ); IProcess b3u = ((IProcessWithDifferentiator) q).ConvertToBase (); System.Console.WriteLine ( "b3u.Process(5) = " + b3u.Process ( 5 ) ); System.Console.ReadLine (); } } 

输出如下:

  ...float Process... a1 .Process(3.3) = -52.45 ...int Process... a2d.Process(4) = 5 ...double Process... a3d.Process(5.5) = 16.248 ...int Process... a2u.Process(4) = 5 ...double Process... a3u.Process(5.5) = 16.248 ...int Process1... b1 .Process(3) = -8 ...int Process2... b2d.Process(4) = 16 ...int Process3... b3d.Process(5) = 100307 ...int Process2... b2u.Process(4) = 16 ...int Process3... b3u.Process(5) = 100307 

问题正是错误消息所说的:

 'IRoot' cannot implement both 'IBase' and 'IBase' because they may unify for some type parameter substitutions 

例如,你可以这样做:

 public class Test : IRoot 

在这种情况下,它将有两个inheritance链到IBase ,这是不允许的。

与往常一样,请尝试包括您遇到的问题以及问题的代码。

这是我的解决方案。 它基于使用差异化,因此您可以清楚自己想要哪个界面。 您必须添加一个否则未使用的参数,但这就是告诉它您想要的参数。

 public interface First { } public interface Second { } public class Processor : IRoot { // Here we want 2 methods public int Process ( int item ) { System.Console.WriteLine ( "int Process" ); return item + 1; } public double Process ( double item ) { System.Console.WriteLine ( "double Process" ); return item + 10.748; } } public class TestProcessor : IRoot { int IProcessWithDifferentiator.Process ( int item ) { System.Console.WriteLine ( "int Process" ); return item + 1; } int IProcessWithDifferentiator.Process ( int item ) { System.Console.WriteLine ( "int Process" ); return item + 100302; } } public interface IProcessWithDifferentiator { TResult Process ( TItem item ); } public interface IRoot : IProcessWithDifferentiator, IProcessWithDifferentiator { } class Program { static void Main ( string [] args ) { Processor p = new Processor (); IProcessWithDifferentiator one = p; System.Console.WriteLine ( "one.Process(4) = " + one.Process ( 4 ) ); IProcessWithDifferentiator two = p; System.Console.WriteLine ( "two.Process(5.5) = " + two.Process ( 5.5 ) ); TestProcessor q = new TestProcessor (); IProcessWithDifferentiator q1 = q; System.Console.WriteLine ( "q1.Process(4) = " + q1.Process ( 4 ) ); IProcessWithDifferentiator q2 = q; System.Console.WriteLine ( "q2.Process(5) = " + q2.Process ( 5 ) ); System.Console.ReadLine (); } } 

这是输出。

 int Process one.Process(4) = 5 double Process two.Process(5.5) = 16.248 int Process q1.Process(4) = 5 int Process q2.Process(5) = 100307 

即使您使用IRoot ,这也可以正常工作IRoot如上所示; 它知道(因为我们告诉它)要使用哪个IDifferentiatedProcess。

(如果重要,我在Visual Studio 2012上。)

据我所知,你想要定义一个这样的界面:

 public interface IRoot where TM : MType where TPM : PMType where TPK : new() { TM Get(TPK key); TPM Get(TPK key); } 

这是不可能的,因为您无法定义具有相同名称和相同参数的两个方法。

 error CS0111: Type 'IRoot' already defines a member called 'Get' with the same parameter types 

尝试直接定义您的接口(没有inheritance)并更改方法名称。 例如:

 public interface IRoot where TM : MType where TPM : PMType where TPK : new() { TM GetTM(TPK key); TPM GetTPM(TPK key); } 

很抱歉看到你有这么多的投票,我面临同样的问题。

遗憾的是它似乎不可能 – 这个MSDN页面列出了唯一可能的generics类型约束,并且没有人可以表达约束“ TU可以是任何类型,但必须具有不同的inheritance层次结构” http://msdn.microsoft .COM / EN-US /库/ d5x73970(v = VS.80)的.aspx

我们真的需要某种where T !: Uwhere T, U disjoint语法; 但是就目前而言,没有办法向编译器指定TItem1TItem2实例永远不能互相替换。