(原創) 一個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}
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
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}
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
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}
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}
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,利用類似多型的方式來處理。