(原創) 一個C++能跑的泛型,但在C#卻不能跑<已解決> (C/C++) (template) (.NET) (C#) (C++/CLI)

ISO C++

 1/* 
 2(C) OOMusou 2007 http://oomusou.cnblogs.com
 3
 4Filename    : Template_test1.cpp
 5Compiler    : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++
 6Description : template test
 7Release     : 06/09/2007 1.0
 8*/

 9#include <iostream>
10
11using namespace std;
12
13class Interface1 {
14public:
15  virtual void func1() = 0;
16}
;
17
18class Interface2 {
19public:
20  virtual void func1() = 0;
21}
;
22
23class Class1 : public Interface1 {
24public:
25  void func1() {
26    cout << "Class1's func1" << endl;
27  }

28}
;
29
30class Class2 : public Interface2 {
31public:
32  void func1() {
33    cout << "Class2's func1" << endl;
34  }

35}
;
36
37class IGeneric {
38public:
39  virtual void func1() = 0;
40}
;
41
42template<typename T>
43class Generic1 : public IGeneric {
44private:
45  T* _aClass;
46
47public:
48  Generic1(T* aClass) {
49    _aClass = aClass;
50  }

51
52  void func1() {
53    _aClass->func1();
54  }

55}
;
56
57int main() {
58 Interface1* obj1 = new Class1;
59 Interface2* obj2 = new Class2;
60 
61 IGeneric* foo = new Generic1<Interface1>(obj1);
62 foo->func1();
63 
64 foo = new Generic1<Interface2>(obj2);
65 foo->func1();
66 
67 delete obj1;
68 delete obj2;
69 delete foo;
70}

執行結果
Class1's func1
Class2's func1

若使用C++/CLI,也是可以實現
 1/* 
 2(C) OOMusou 2007 http://oomusou.cnblogs.com
 3
 4Filename    : Template_test1.cpp
 5Compiler    : Visual C++ 8.0 / C++/CLI
 6Description : template test
 7Release     : 06/09/2007 1.0
 8*/

 9#include "stdafx.h"
10
11using namespace System;
12
13interface class Interface1 {
14  void func1();  
15}
;
16
17interface class Interface2 {
18  void func1();
19}
;
20
21ref class Class1 : public Interface1 {
22public:
23  virtual void func1() {
24    Console::WriteLine("Class1's func1");
25  }

26}
;
27
28ref class Class2 : public Interface2 {
29public:
30  virtual void func1() {
31    Console::WriteLine("Class2's func1");
32  }

33}
;
34
35interface class IGeneric {
36  void func1();
37}
;
38
39template<typename T>
40ref class Generic1 : public IGeneric {
41private:
42  T^ _aClass;
43
44public:
45  Generic1(T^ aClass) {
46    _aClass = aClass;
47  }

48
49  virtual void func1() {
50    _aClass->func1();
51  }

52}
;
53
54int main() {
55 Interface1^ obj1 = gcnew Class1;
56 Interface2^ obj2 = gcnew Class2;
57 
58 IGeneric^ foo = gcnew Generic1<Interface1>(obj1);
59 foo->func1();
60 
61 foo = gcnew Generic1<Interface2>(obj2);
62 foo->func1();
63}

執行結果
Class1's func1
Class2's func1

若用C#,以下代碼無法compile成功
 1using System;
 2
 3public interface Interface1 {
 4  void func1();
 5}

 6
 7public interface Interface2 {
 8  void func1();
 9}

10
11public class Class1 : Interface1 {
12  public void func1() {
13    Console.WriteLine("Class1's func1");
14  }

15}

16
17public class Class2 : Interface2 {
18  public void func1() {
19    Console.WriteLine("Class2's func1");
20  }

21}

22
23public interface IGeneric {
24  void func1();
25}

26
27public class Generic1<T> : IGeneric where T : Interface1, Interface2 {
28  private T _aClass;
29  
30  public Generic1(T aClass) {
31    _aClass = aClass;    
32  }

33  
34  public void func1() {
35    _aClass.func1();
36  }

37}

38
39public class main {
40  public static void Main() {
41    Interface1 obj1 = new Class1();
42    Interface2 obj2 = new Class2();
43    
44    IGeneric foo = new Generic1<Interface1>(obj1);
45    foo.func1();
46
47    foo = new Generic1<Interface2>(obj2);
48    foo.func1();
49  }

50}

C#無法compile成功
錯誤訊息為
Error 1 The call is ambiguous between the following methods or properties: 'Interface1.func1()' and 'Interface2.func1()' D:\__Clare\CSharp\CSharpLab\Class3.cs 43 5 CSharpLab

Error 2 The type 'Interface1' must be convertible to 'Interface2' in order to use it as parameter 'T' in the generic type or method 'Generic1<T>' D:\__Clare\CSharp\CSharpLab\Class3.cs 52 24 CSharpLab

Error 3 The type 'Interface2' must be convertible to 'Interface1' in order to use it as parameter 'T' in the generic type or method 'Generic1<T>' D:\__Clare\CSharp\CSharpLab\Class3.cs 55 15 CSharpLab

Error1我能理解為什麼不能過,不過並非我故意惡搞,因為實務上的確愈到這樣的需求...
Error2和Error3則真的無法理解了..

看來C#的泛型和C++泛型差異頗大...

請各位指點,該怎麼改才好,改了兩天想不出來...。

<06/16/2007>感謝hyifeng多次的指點,C#的Generics寫法如下
 1/* 
 2(C) OOMusou 2007 http://oomusou.cnblogs.com
 3
 4Filename    : Generics_Test1.cs
 5Compiler    : Visual Studio 2005 / C# 2.0
 6Description : Generics Test
 7Release     : 06/16/2007 1.0
 8*/

 9using System;
10
11public interface InterfaceBase {
12  void func1();
13}

14
15public interface Interface1 : InterfaceBase {
16}

17
18public interface Interface2 : InterfaceBase {
19}

20
21public class Class1 : Interface1 {
22  public void func1() {
23    Console.WriteLine("Class1's func1");
24  }

25}

26
27public class Class2 : Interface2 {
28  public void func1() {
29    Console.WriteLine("Class2's func1");
30  }

31}

32
33public interface IGeneric {
34  void func1();
35}

36
37public class Generic1<T> : IGeneric where T : InterfaceBase {
38  private T _aClass;
39  
40  public Generic1(T aClass) {
41    _aClass = aClass;    
42  }

43  
44  public void func1() {
45    _aClass.func1();
46  }

47}

48
49public class main {
50  public static void Main() {
51    Interface1 obj1 = new Class1();
52    Interface2 obj2 = new Class2();
53    
54    IGeneric foo = new Generic1<Interface1>(obj1);
55    foo.func1();
56
57    foo = new Generic1<Interface2>(obj2);
58    foo.func1();
59  }

60}

之前C#寫法,主要錯誤為
public class Generic1<T> : IGeneric where T : Interface1, Interface2
我以為是T可以是Interface1 OR Interface2,但實際上是T必須同時implement Interface1 AND Interface2,所以在C#須將相同的Interface提升至InterfaceBase,利用類似多型的方式來處理。

posted on 2007-06-16 14:16  真 OO无双  阅读(3837)  评论(27编辑  收藏  举报

导航