ホームページ  >  記事  >  バックエンド開発  >  C# 汎用プログラミング

C# 汎用プログラミング

黄舟
黄舟オリジナル
2016-12-21 14:47:351017ブラウズ

ジェネリック: パラメーター化された型を使用して、同じコード上で複数のデータ型を操作します。 「パラメータ化された型」を使用して型を抽象化し、柔軟な再利用を実現します。 Test test = new Test(obj); Console.WriteLine("int:" --

Console.WriteLine(" String: " + test1.obj);

Console.Read(); パブリック T obj;

パブリック テスト(T obj)

This.obj =

プログラム分析:

1. テストは汎用クラスです。 T はインスタンス化されるジェネリック型です。 T が int 型としてインスタンス化される場合、メンバー変数 obj は int 型になります。T が string 型としてインスタンス化される場合、obj は string 型になります。

2. タイプに応じて、上記のプログラムは異なる値を表示します。



C# ジェネリック メカニズム:

C# ジェネリック機能は、実行時に CLR によってサポートされます。C# ジェネリック コードが IL コードおよびメタデータにコンパイルされるとき、ジェネリック型を表すために特別なプレースホルダーが使用され、特別な一部の IL 命令はジェネリック操作をサポートします。実際の汎用インスタンス化作業は、JIT コンパイル中に「オンデマンド」方式で発生します。



今のコードのMain関数のメタデータを見てください

.method private Hidebysig static void Main(string[] args) cil Managed

{

.entrypoint

// コードサイズ 79 (0x4f) )

.maxstack 2

.locals init ([0] int32 obj,

[1] クラス CSharpStudy1.Test`1 テスト,

[2] 文字列 obj2,

[3] クラスハープ研究1. Test` 1 test1)

IL_0000: nop

IL_0002: stloc.0

IL_0003: ldloc.0

IL_00 04: newobj インスタンス void クラスCSharpStudy1.Test`1< ;int32> ::.ctor(!0)

IL_0009: stloc.1

IL_000f: ldloc.1

IL_0010: ldfld !0 クラス CSharpStudy1< ;int32> ::obj : IL_0015: BOX [mscorlib] System.int32

IL_001a: 文字列の呼び出し [mscorkibb] System.string :: concat (オブジェクト,

オブジェクト)

ie_001f: void [mscorlib] system.con.con ソールの呼び出し:: writeline (文字列)

IL_0024: nop

IL_0025: ldstr "hello world"

  IL_002a: stloc.2

IL_002b: ldloc.2

IL_002c: newobj インスタンス void class CSharpStudy1.Test`1::.ctor(!0)

IL_0031: stloc.3

IL_0032: ldstr 「文字列」 :"

IL_0037: ldloc.3

IL_0038: ldfld !0 class CSharpStudy1.Test`1::obj

IL_003d: call string [mscorlib]System.String::Concat (文字列,

文字列)

IL_0042: call void [mscorlib]System.Console::WriteLine(string)

IL_0047: nop

IL_0048: call int32 [mscorlib]System.Console::Read()

IL _004d: ポップ

IL_004e: レット

} // メソッドの終わり Program::Main



戻って見るTest类中构造関数数的元数据

.method public Hidebysigspecialname rtspecialname

instance void .ctor(!T obj) cil maned

{

// コードサイズ 17 (0x11)

.maxstack 8

IL_0000: ldarg.0

IL_0001: call instance void [mscorlib]System.Object::.ctor()

IL_0006: いや

IL_0007 : nop

IL_0008: ldarg.0

IL_0009: ldarg.1

IL_000a: stfld !0 クラス ConsoleCSharpTest1.Test`1::obj

IL_0 00f: いいえ

IL_0010: ret

} / / メソッドの終わり Test`1::.ctor



1、第一轮编译時、编译器のみTest種類生成“泛型版”のIL代码与元データ据——并不実行例: Test 型要素データ内に表示される

2、JIT 輻輳時、JIT エミュレータが最初に Test に遭遇したとき例: Main 関数に表示されている

3、CLR はすべてのタイプのパラメータです。 「参照型」の型は同じコードを生成しますが、型パラメータが「値型」の場合は、異なる「値型」ごとに CLR が独立したコードを生成します。


C# 型の場合、内部ストレージに割り当てられるサイズは同様ですが、ある値のタイプを例にすると、内部ストレージに割り当てられるサイズは異なります。型のパラメータは同じですが、JIT ブラウザはこの型を繰り返し使用するため、C# の動的型の機能により、C++ 静的モジュールによって引き起こされる可能性のあるコード拡張の問題が回避されます。元のデータであるため、C# の型は、大規模なリフレクション技術に使用できます。 「表示约束」は、型の安全性を高めると同時に、「签名」の型束に基づく C++ モジュールが持つ高い活性性を失いました



C#泛型继承:

C#削除可能個別に参照できる约型类型(タイプと構造を含む)さらに、ベースタイプの中に、サブタイプのタイプのマニュアルを含めることもできます。注記のタイプパラメータ、次のようなタイプを参照してください。 ,V>:C

クラス G:C  //非法

E型はC型に提供されており、U、V、つまり上の説明です、子クラス

F型からCに継承されており、F型から見ることができます。分類

G 型は非法的です、G 型は泛型ではないため、C は泛型であり、G 無法给C は泛型を提供します



ジェネリック型のメンバー:

ジェネリック型のメンバーは、ジェネリック型宣言で型パラメーターを使用できます。ただし、型パラメーターに制約がない場合は、その型で System.Object から継承されたパブリック メンバーのみを使用できます。以下に示すように:




ジェネリック インターフェイス:

ジェネリック インターフェイスの型パラメーターは、インスタンス化されるか、実装クラスによって宣言された型パラメーターから派生します



ジェネリック デリゲート:

ジェネリック デリゲートは委任をサポートします パラメーターの型これらのパラメータの型には、法的な制約が伴う場合もあります

delegate bool MyDelegate(T value);

class MyClass

{

static bool F(int i){.. .}

static bool G(string s){...}

static void Main()

{

MyDelegate p2 = G;

MyDelegate p1 = new My Delegate ( F);

}

}



ジェネリック メソッド:

1. C# のジェネリック メカニズムは、「メソッド宣言に型パラメーターを含む」、つまりジェネリック メソッドのみをサポートします。

2. C# のジェネリック メカニズムでは、メソッドを除く他のメンバー (プロパティ、イベント、インデクサー、コンストラクター、デストラクターを含む) の宣言に型パラメーターを含めることはサポートされていませんが、これらのメンバー自体はジェネリック型に含めることができます。ジェネリック型の型パラメーターを使用します。

3. ジェネリック メソッドは、ジェネリック型と非ジェネリック型の両方に含めることができます。



ジェネリックメソッド宣言: 以下の通り

public static int FunctionName(T value){...}



ジェネリックメソッドのオーバーロード:

public void Function1(T a );

public void Function1(U a);

これは、ジェネリック メソッドのオーバーロードを構成することはできません。コンパイラはジェネリック型 T と U が異なるかどうかを判断できないため、2 つのメソッドが異なるかどうかを判断できません



public void Function1(int x);

public void Function1(int x);

これはオーバーロードを構成する可能性があります



public void Function1(T t) where T:A;

public void Function1(T t) where T:B;

これはジェネリック メソッドを構成することはできません過負荷の。コンパイラは制約内の A と B が異なるかどうかを判断できないため、2 つのメソッドが異なるかどうかを判断できません。デフォルトで継承されます。以下の通り:

abstract class Base

{

public abstract T F(T t,U u) where U:T;

public abstract T G(T t) where T: IComparable ;

}



class MyClass:Base

{

public override ) ここで、T:IComparable{}

}

MyClass の 2 つのオーバーライドされたメソッドについては、

F メソッドが有効であり、制約は次によって継承されます。デフォルトの

G メソッドは不正であり、制約の指定は冗長です



ジェネリック制約:

1. C# ジェネリックでは、「すべてのジェネリック型またはジェネリック メソッドの型パラメーター」に関する仮定は「明示的な制約」に基づいている必要があります。 C# の型安全性によって要求される要件を維持するため。

2. 「明示的な制約」はwhere句で表現され、「基底クラス制約」「インターフェース制約」「コンストラクタ制約」「値型・参照型制約」の4種類の制約を指定できます。

3. 「明示的な制約」は必要ありません。「明示的な制約」が指定されていない場合、ジェネリック型パラメーターは System.Object 型のパブリック メソッドにのみアクセスできます。例: 最初の例では、obj メンバー変数が定義されています。たとえば、以下に示すように、Test1 クラスを最初の例に追加し、その中に 2 つのパブリック メソッド Func1 と Func2 を定義します。






これらの制約の分析を始めましょう:

Base クラスの制約:

class A public Public void func1 func2()

t//S の変数は Func1 メソッドを呼び出すことができます

s.Func1();

//T の変数は Func2 メソッドを呼び出すことができます

t.Func2();

}

インターフェースの制約:

インターフェース IA < ;

}



インターフェイス IC

{

T Func3();

}



class MyClass

where T : IA

どこでV : IB, IC

{

public MyClass(T t, V)

// T のオブジェクトは Func1 を呼び出すことができます。

t.Func1(); v.Func2();

v. Func3() );

}

}

コンストラクター制約:

クラス A


,,,,,,,,,,,,,,,,,,,,,,,, )

public c()
{��; '真実の型または方法 C & lt; t & gt;

注: C# は現在パラメーターなしのコンストラクター制約のみをサポートしています

現時点では、型 B のパラメーター化されたコンストラクターを作成したため、システムは自動的にB のパラメータなしのコンストラクタですが、型 B にパラメータなしのコンストラクタを追加すると、オブジェクト d のインスタンス化ではエラーが報告されません。 B タイプは次のように定義されます:

クラス B

{

B() タイプ/参照type:

public struct A { }

public class B { }



T : struct

;

C
c2 オブジェクトはコンパイル時にエラーが発生します: 型 'B' をジェネリック型またはメソッドのパラメーター 'T' として使用するには、null 非許容値型である必要があります。 C



概要:

1. C# の汎用機能は、コンパイル時に C++ によってサポートされる静的テンプレートとは異なり、単純な「ワイピング メソッド」とも異なります。 Java ではジェネリックのコンパイラ レベルでサポートされています。

2. C# のジェネリック サポートには、クラス、構造体、インターフェイス、デリゲート、メソッド メンバーの 4 つのジェネリック型が含まれます。

3. C# のジェネリックスは、「基本クラス、インターフェイス、コンストラクター、値型/参照型」の制約メソッドを使用して、型パラメーターに「明示的な制約」を実装します。C++ の数式制約のような、暗黙的なシグネチャベースの制約はサポートされません。 。

上記は C# の汎用プログラミングの内容です。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) をご覧ください。



声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。