2009-08-17 25 views
4

我认为这个例子会更清晰。我们希望在处理器类中看到两种具有不同参数的方法。 “int Process(int value);” “double Process(double value);”如何在界面中使用不同模板参数两次使用相同的界面?

但编译器对IRoot表示: 'Generics.IRoot'无法同时实现'Generics.IProcess'和'Generics.IProcess',因为它们可能会统一某些类型参数替换。

public class Processor : IRoot<int, double, int, double> 
{ 
    // Here we want 2 methods 
    public int Process(int item) { } 
    public double Process(double item) { } 
} 

public interface IProcess<TResult, TItem> 
{ 
    TResult Process(TItem item); 
} 

public interface IRoot<TR1, TR2, TItem1, TItem2> : 
    IProcess<TR1, TItem1>, 
    IProcess<TR2, TItem2> 
{ 

} 
+1

有什么问题吗?从代码中绝对不清楚......给出一些细节和解释,而不仅仅是一段代码! – 2009-08-17 09:47:06

+0

问题在标题中:“如何在界面中使用不同模板参数两次使用相同的界面?” – 2009-08-17 10:45:42

+0

问题是,我们可以尝试弄清楚为什么*你不能这样做的唯一方法是将代码复制并粘贴到编译器中,并尝试编译它。你应该发布你从编译器得到的错误消息,这使得人们更容易回答。永远不要假设人们会为了帮助你而跳过许多箍环,帮助我们帮助你,为我们提供尽可能多的信息。 – 2009-08-17 11:17:14

回答

-3

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

public interface IBase<TM, TPkey> 
    where TM : bType 
    where TPkey : new()   
{ 
    TM Get(TPkey key); 
} 

public interface IABase<TPK> : IBase<ConcreteTmA, TPK> {} 
public interface IBBase<TPK> : IBase<ConcreteTmB, TPK> {} 

public class Root <TPK> : 
    IABase<TPK>, 
    IBBase<TPK> 
    where TM : MType 
    where TPM : PMType 
    where TPK : new() 
{ 
    ConcreteTmA IABase.Get(TPK key) 
    { 
    } 

    ConcreteTmB IBBase.Get(TPK key) 
    { 
    } 
} 
+0

我在这里不理解你的代码,你有没有{..}块的接口,你有一个接口有方法实现,你在IRoot中有比泛型参数更通用的参数约束,等等。 “可能”一词,并使代码至少能够编译。 – 2009-08-17 10:23:44

+0

修正了括号,我想每个人都知道我的意思是......是 – 2009-08-17 12:04:55

+0

的“可能的字”,因为该解决方案是唯一可行的,如果有种类尽可能TM,如果IRoot数量有限,没有所有的通用参数是可以接受的。 – 2009-08-17 12:19:37

1

据我了解,你要这样定义一个接口:

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

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

error CS0111: Type 'IRoot<TM,TPM,TPK>' already defines a member called 'Get' with the same parameter types 

尝试直接定义您的接口(不带继承)并更改方法名称。例如:

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

的问题是完全错误信息说什么:

'IRoot<TM,TPM,TPK>' cannot implement both 'IBase<TM,TPK>' and 
'IBase<TPM,TPK>' because they may unify for some type parameter substitutions 

举例来说,你可以这样做:

public class Test : IRoot<Int32, Int32, Int32> 

在这种情况下,将有两个继承链接到IBase<Int32, Int32>这是不允许的。

一如既往,请尽量包括您遇到的问题以及代码的问题。

1

对不起,看到你有这么多downvotes对此,我面临同样的问题。

可悲的是它似乎没有可能 - 这个MSDN页面列出了唯一可能的泛型类型的限制,并没有能表达约束“TU可以是任何类型的,但必须有不同的继承层次” http://msdn.microsoft.com/en-us/library/d5x73970(v=vs.80).aspx

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

+0

是的,我也是。来自所有可能的外部空间,你需要特殊的语言能力来命名或识别你可能投掷对象的单个基地,所以即使在统一时它们也可以保持分开。 – 2012-09-11 00:29:00

+0

见下面我的解决方案... – 2012-09-11 01:13:07

2

这是我的解决方案。它基于使用差异化,所以你可以清楚你想要哪个界面。你必须添加一个其他未使用的参数,但这就是告诉它你想要的。

public interface First { } 
public interface Second { } 

public class Processor : IRoot<int, double, int, double> 
{ 
    // 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, int, int, int> 
{ 
    int IProcessWithDifferentiator<int, int, First>.Process (int item) 
    { 
     System.Console.WriteLine ("int Process"); return item + 1; 
    } 
    int IProcessWithDifferentiator<int, int, Second>.Process (int item) 
    { 
     System.Console.WriteLine ("int Process"); return item + 100302; 
    } 
} 

public interface IProcessWithDifferentiator<TResult, TItem, TDiff> 
{ 
    TResult Process (TItem item); 
} 

public interface IRoot<TR1, TR2, TItem1, TItem2> : 
    IProcessWithDifferentiator<TR1, TItem1, First>, 
    IProcessWithDifferentiator<TR2, TItem2, Second> 
{ 

} 

class Program 
{ 
    static void Main (string [] args) 
    { 
     Processor p = new Processor(); 
     IProcessWithDifferentiator<int, int, First> one = p; 
     System.Console.WriteLine ("one.Process(4) = " + one.Process (4)); 
     IProcessWithDifferentiator<double, double, Second> two = p; 
     System.Console.WriteLine ("two.Process(5.5) = " + two.Process (5.5)); 

     TestProcessor q = new TestProcessor(); 
     IProcessWithDifferentiator<int, int, First> q1 = q; 
     System.Console.WriteLine ("q1.Process(4) = " + q1.Process (4)); 
     IProcessWithDifferentiator<int, int, Second> 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<int,int,int,int>,您也可以在上面看到;它知道(因为我们告诉它)使用哪个IDifferentiatedProcess。

(在它的事项的情况下,我在Visual Studio中2012年)

+0

富有想象力的解决方案,看起来我们要能够做到用C# – 2012-09-11 10:27:34

+0

我还在寻找一种方式来以后删除differenting参数最好的... – 2012-09-11 14:20:34

+0

我已经发布第二个答案是解决删除他的区分参数,但可悲的是,它有点难看,使用代理。 – 2012-09-11 19:03:02

3

所以张贴我首先回答这个问题(#1)后,我才明白,人们常常会希望能够将一个值从转换与非差异化界面的差异化界面。换句话说,一个想要做以下

IProcessWithDifferentiator<TRes, TItem, TDiff> : IProcess<TRes, TItem> 

但我们不能因为我们会碰到同样的错误使用接口时(类型可能统一)。

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

因此,回到绘图板,并返回一个丑陋的解决方案,这是有一个方法返回向下转换的类型,和一个代理来支持这种方法的构造。 (唯一可以缓解的问题是,如下所示,代理类可以稍微重用。)以下是本练习的结果。

public interface Second { } 
public interface Third { } 

public class Processor : IRoot<float, int, double, float, int, double> 
{ 
    // 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<int, int> IProcessWithDifferentiator<int, int, Second>.ConvertToBase() 
    { 
     return new TP_Proxy<int, int, Second> (this); 
    } 

    IProcess<double, double> IProcessWithDifferentiator<double, double, Third>.ConvertToBase() 
    { 
     return new TP_Proxy<double, double, Third> (this); 
    } 
} 

public class TestProcessor : IRoot<int, int, int, int, int, int> 
{ 
    int IProcess<int, int>.Process (int item) 
    { 
     System.Console.WriteLine (" ...int Process1..."); return item - 11; 
    } 
    int IProcessWithDifferentiator<int, int, Second>.Process (int item) 
    { 
     System.Console.WriteLine (" ...int Process2..."); return item + 12; 
    } 
    int IProcessWithDifferentiator<int, int, Third>.Process (int item) 
    { 
     System.Console.WriteLine (" ...int Process3..."); return item + 100302; 
    } 

    IProcess<int, int> IProcessWithDifferentiator<int, int, Second>.ConvertToBase() 
    { 
     return new TP_Proxy<int, int, Second> (this); 
    } 

    IProcess<int, int> IProcessWithDifferentiator<int, int, Third>.ConvertToBase() 
    { 
     return new TP_Proxy<int, int, Third> (this); 
    } 
} 

public interface IProcess<TResult, TItem> 
{ 
    TResult Process (TItem item); 
} 

public interface IProcessWithDifferentiator<TResult, TItem, TDiff> // would love to ": IProcess<TResult, TItem>" here but won't work above 
{ 
    TResult Process (TItem item); // replicated method from IProcess... yuck(!) 
    IProcess<TResult, TItem> ConvertToBase(); 
} 

// Having a proxy sucks. But at least this proxy is shared among multiple classes implementing the IProcess concept. 
class TP_Proxy<TResult, TItem, TDiff> : IProcess<TResult, TItem> 
{ 
    public TP_Proxy (IProcessWithDifferentiator<TResult, TItem, TDiff> px) { _proxyTo = px; } 
    private IProcessWithDifferentiator<TResult, TItem, TDiff> _proxyTo; 
    TResult IProcess<TResult, TItem>.Process (TItem item) { return _proxyTo.Process (item); } 
} 

public interface IRoot<TR1, TR2, TR3, TItem1, TItem2, TItem3> : 
    IProcess<TR1, TItem1>, 
    IProcessWithDifferentiator<TR2, TItem2, Second>, 
    IProcessWithDifferentiator<TR3, TItem3, Third> 
{ 
} 

class Program 
{ 
    static void Main (string [] args) 
    { 
     Processor p = new Processor(); 
     // Direct conversion of first one, of course 
     IProcess<float, float> a1 = p; 
     System.Console.WriteLine ("a1 .Process(3.3) = " + a1.Process ((float) 3.3)); 

     // Conversion of differentiated class 
     IProcessWithDifferentiator<int, int, Second> a2 = ((IProcessWithDifferentiator<int, int, Second>) p); 
     System.Console.WriteLine ("a2d.Process(4)  = " + a2.Process (4)); 
     IProcessWithDifferentiator<double, double, Third> a3 = (IProcessWithDifferentiator<double, double, Third>) p; 
     System.Console.WriteLine ("a3d.Process(5.5) = " + a3.Process (5.5)); 

     // Conversions to undifferentiated class using ugly proxies 
     IProcess<int, int> a2u = ((IProcessWithDifferentiator<int, int, Second>) p).ConvertToBase(); 
     System.Console.WriteLine ("a2u.Process(4)  = " + a2u.Process (4)); 
     IProcess<double, double> a3u = ((IProcessWithDifferentiator<double, double, Third>) p).ConvertToBase(); 
     System.Console.WriteLine ("a3u.Process(5.5) = " + a3u.Process (5.5)); 

     TestProcessor q = new TestProcessor(); 

     IProcess<int, int> b1 = q; 
     // Direct conversion of first one, of course 
     System.Console.WriteLine ("b1 .Process(3)  = " + b1.Process (3)); 

     // Conversion of differentiated class 
     IProcessWithDifferentiator<int, int, Second> b2d = (IProcessWithDifferentiator<int, int, Second>) q; 
     System.Console.WriteLine ("b2d.Process(4)  = " + b2d.Process (4)); 
     IProcessWithDifferentiator<int, int, Third> b3d = (IProcessWithDifferentiator<int, int, Third>) q; 
     System.Console.WriteLine ("b3d.Process(5)  = " + b3d.Process (5)); 

     // Conversions to undifferentiated class using ugly proxies 
     IProcess<int, int> b2u = ((IProcessWithDifferentiator<int, int, Second>) q).ConvertToBase(); 
     System.Console.WriteLine ("b2u.Process(4)  = " + b2u.Process (4)); 
     IProcess<int, int> b3u = ((IProcessWithDifferentiator<int, int, Third>) 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 
相关问题