2009-08-17 28 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 
相關問題