.NET Framework 4の互換性の問題
15750 ワード
テストプログラム
次の非常に簡単なCプログラムTesterを見てみましょう.cs:
1 using System;
2
3 static class Tester
4 {
5 static void Main()
6 {
7 Console.WriteLine(" CLR: " + Environment.Version);
8 Console.WriteLine("Concat: " + string.Concat(new int[]{12, 345}));
9 }
10 }
このテストプログラムの実質的な内容は1行だけで,8行目でstringクラスの静的メソッドConcatを呼び出した.
実行結果
上記のテストプログラムの実行結果を見てみましょう.まずLinuxオペレーティングシステムのMono環境です.
ben@vbox:~/work> gmcs Tester.cs && mono Tester.exe
CLR: 2.0.50727.1433
Concat: System.Int32[]
ben@vbox:~/work> dmcs Tester.cs && mono Tester.exe
CLR: 4.0.30319.1
Concat: 12345
WindowsオペレーティングシステムのMicrosoftもあります.NET Framework環境:
D:\work> C:\Windows\Microsoft.NET\Framework\v2.0.50727\csc.exe Tester.cs
Microsoft (R) Visual C# 2005 8.00.50727.4016
Microsoft (R) Windows (R) 2005 Framework 2.0.50727
(C) Microsoft Corporation 2001-2005。 。
D:\work> Tester.exe
CLR: 2.0.50727.4216
Concat: System.Int32[]
D:\work> C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe Tester.cs
Microsoft(R) Visual C# 2010 4.0.30319.1
(C) Microsoft Corporation。 。
D:\work> Tester.exe
CLR: 4.0.30319.276
Concat: 12345
同じC#プログラムで、LinuxオペレーティングシステムでもWindowsオペレーティングシステムでも、NET Framework 2.0と.NET Framework 4の間には互換性がないことが示されている.
ぶんせき
上記の運転結果は、主にstring類の静的方法Concatがあるためである.NET Framework 2.0には9種類のリロードバージョンがあります.NET Framework 4には11種類のリロードバージョンがあります.上記テスト用のC#プログラムで実際に呼び出されたリロードバージョンは以下の通りです.
.NET Framework 2.0: public static string Concat(Object arg0)
.NET Framework 4 : public static string Concat<T>(IEnumerable<T> values)
どうやらNET Framework Base Class Libraryで新しい方法を追加するのも安全ではなく、既存のC#プログラムの動作を変える可能性があります.これは私たちに既存のプログラムをNET Framework 2.0行き.NET Framework 4の移行には注意が必要です.MSDNで「バージョン注意事項」が明確に指摘されている点だけでなく、微妙な変更にも注意してください.
ILコードの表示
Linuxオペレーティングシステムの下で次のコマンドを実行してTesterを逆アセンブリします.ExceはILASMソースファイル:
ben@vbox:~/work> gmcs Tester.cs && monodis Tester.exe > Tester-v2.il
ben@vbox:~/work> dmcs Tester.cs && monodis Tester.exe > Tester-v4.il
次はTester-v 2です.ilファイル:
1 .assembly extern mscorlib
2 {
3 .ver 2:0:0:0
4 .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
5 }
6 .assembly 'Tester'
7 {
8 .custom instance void class [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::'.ctor'() = (
9 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
10 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
11
12 .hash algorithm 0x00008004
13 .ver 0:0:0:0
14 }
15 .module Tester.exe // GUID = {9F6A8C8F-B962-4E6A-A4E9-FA6FF9E83982}
16
17
18 .class private auto ansi abstract sealed beforefieldinit Tester
19 extends [mscorlib]System.Object
20 {
21
22 // method line 1
23 .method private static hidebysig
24 default void Main () cil managed
25 {
26 // Method begins at RVA 0x20ec
27 .entrypoint
28 // Code size 60 (0x3c)
29 .maxstack 8
30 IL_0000: ldstr " CLR: "
31 IL_0005: call class [mscorlib]System.Version class [mscorlib]System.Environment::get_Version()
32 IL_000a: call string string::Concat(object, object)
33 IL_000f: call void class [mscorlib]System.Console::WriteLine(string)
34 IL_0014: ldstr "Concat: "
35 IL_0019: ldc.i4.2
36 IL_001a: newarr [mscorlib]System.Int32
37 IL_001f: dup
38 IL_0020: ldc.i4.0
39 IL_0021: ldc.i4.s 0x0c
40 IL_0023: stelem.i4
41 IL_0024: dup
42 IL_0025: ldc.i4.1
43 IL_0026: ldc.i4 345
44 IL_002b: stelem.i4
45 IL_002c: call string string::Concat(object)
46 IL_0031: call string string::Concat(string, string)
47 IL_0036: call void class [mscorlib]System.Console::WriteLine(string)
48 IL_003b: ret
49 } // end of method Tester::Main
50
51 } // end of class Tester
さらにdiffコマンドを使用してTester-v 4を見てみましょう.ilとTester-v 2.ilの違い:
ben@vbox:~/work> diff Tester-v2.il Tester-v4.il
3c3
< .ver 2:0:0:0
---
> .ver 4:0:0:0
15c15
< .module Tester.exe // GUID = {9F6A8C8F-B962-4E6A-A4E9-FA6FF9E83982}
---
> .module Tester.exe // GUID = {D564CE72-73D3-43DD-B6F4-FB12809D5589}
45c45
< IL_002c: call string string::Concat(object)
---
> IL_002c: call string string::Concat<int32> (class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)
全部で3つの違いしかありません.
上記の3点目の違いは、前節の分析を検証し、対応する呼び出しのConcatメソッドの異なるリロードバージョンを明確に示しています.