C#属性とタイプ

アーティストのブラシは異なる場合もあれば、ブラシがまったくない場合もあります。 C ++では、型は翻訳後に消えましたが、C#では消えず、実行時に使用できます。 C#は、小規模製品で太りすぎたDelphiであり、型で属性を使用する主な理由は、以前のTValueListEditorであったPropertyGridです。 それでは、型を持つ属性は単純で便利であるという明らかでない結論に達することができます。



以前は、クラスのメソッド、フィールド、およびプロパティは純粋にコーダーの間のFeneyであり、メソッドと言うことも、関数と言うことも、フィールドとすることも、変数だけとすることもできました。 しかし、メモリに型があるとすぐにアクセスでき、アドレス指定には正確な用語を使用する必要があります。 任意のオブジェクトからそのタイプを取得でき、タイプからフィールド、プロパティ、およびメソッドの名前を取得でき、名前によってフィールドの値を取得できます-つまり 別のオブジェクト、またはすべてのパラメーターと戻り値でメソッドを呼び出します。



class X { class A { public int f1; public int p1 { get; set; } public int m1(string s, int i) { return (0); } } X() { A a = new A(); Type t = a.GetType(); FieldInfo fi = t.GetField("f1"); object of = fi.GetValue(a); PropertyInfo pi = t.GetProperty("p1"); MethodInfo mpi = pi.GetGetMethod(); object ompi = mpi.Invoke(a, null); MethodInfo mi = t.GetMethod("m1"); object om = mi.Invoke(a, new object[] { "param1", 2 }); } }
      
      





このように、変数自体ではなく、文字列名を書くことができる場合、代替の絡み合ったプログラミング方法が得られました。 文字列名は変更できます。



各オブジェクトには2つの仮説があります。一方では、あるタイプのフィールドであり、他方では、異なるフィールドが存在できる独自のタイプがあります。 実行時の型は、ハッカーメソッドを使用してメモリ内のアドレスにアクセスする場合を除き、変更できません。



各タイプには属性のリストがあり、このリストは空の場合もあれば、完全な場合もあります。 ここからが楽しみです。 各オブジェクトには固有のタイプがあります。 つまり、int型の2つの変数には2つの異なる型があります。 これらのタイプは同じ場合もあれば、異なる場合もあり、属性のリストが異なります。 exe-shnikが重複した型でオーバーフローしていないことは明らかです。実装はリンクを通過しますが、エンコーダレベルの穴あき表現ではこれはまさにそうです。



  class X { class ATTR1 : Attribute { public ATTR1() { } } class ATTR2 : Attribute { public ATTR2() { } } class A { [ATTR1] public int i1; [ATTR2] public int i2; } X() { object[] ai1 = a.GetType().GetField("i1").GetCustomAttributes(false); object[] ai2 = a.GetType().GetField("i2").GetCustomAttributes(false); } }
      
      





オブジェクトには属性がなく、タイプのみに属性があります。 各オブジェクトからその型を取得し、その型の属性を見つけることができます。 しかし、各オブジェクトのタイプは一意であるため、オブジェクトには属性があると言えます。 ただし、オブジェクトは特定のタイプで記述され、このタイプでは属性もこのオブジェクトに割り当てられていると言えます。 したがって、オブジェクトには2つの属性リストがあります。それ自体のタイプによるリストと、このオブジェクトが記述されているタイプによるリストです。



  class X { class ATTR1 : Attribute { public ATTR1() { } } class ATTR2 : Attribute { public ATTR2() { } } [ATTR1] public class A { } [ATTR2] public A a; X() { a = new A(); object[] inner = a.GetType().GetCustomAttributes(false); object[] outer = this.GetType().GetField("a").GetCustomAttributes(false); } }
      
      





フィールドには属性だけでなく、メソッドとプロパティもあります。 属性を使用するには、まずオブジェクトで属性を見つける必要があります。 オブジェクトから属性を探すときは、適切なリストを選択する必要があり、属性を規定するときは、それぞれ次のタイプで記述する必要があります。 多くの場合、万一の場合、エンコーダはあちこちで属性をチェックし、属性が競合する場合は、type属性よりもfield属性を優先します。



原始的なコーダーは、主なことはプログラムをコーディングすることだと信じていました。 その後、祖先は、データを構造化することが主なものであるという結論に達しました。 私たちの賢明な時代に、普遍的なプログラムはデータの構造化された海の広がりを耕し、そこに新しい秩序をもたらします。 同じプログラムの1つにPropertyGridがあります。これは、変更可能なデータツリーを表示します。 彼は公有財産を見つけるとすぐにそれを見せます。 また、プロパティが非常に非標準で、表示も編集もできない場合、PropertyGridはクラスの説明を持つ属性を検索し、プロパティを表示および修正できます。 そして、彼がそれを見つけなければ、彼はそれを見せません。 しかし、DBMSにはデータのタイプが長く保存されており、プログラムに保存してみてください。コンピューターにメモリを追加する場所がなく、制御されていない部分を高速でコーディングできます。



既知の不具合。



Usoはc#内で動作しますが、OLE(COM、ActiveX)で公開する価値があります。いくつかの属性はすぐに失われるため、おそらくc#dllから別のdllに移動するときにそうなります。 たとえば、フィールド自体が1つのdllで記述され、属性を持つそのタイプが別のdllで記述され、属性が消えない場合、その空き地は消えます-これもまたクラスです。 グリッチがどこにあるかを正確に判断することは困難です。 ほとんどの場合、CCWが吹きます。 CCWは、アンマネージコール用のガベージコレクターを備えたラッパーを意味する魔法のような言葉です。 Sharpovtsyは、コーダーはシャープに書き込み、時折プラスの古い成果を引き出すと信じており、コーダー自身は、シャープでピースを仕上げることでモンスターに同行すると信じています。



CCWは送信すべきでないものをガベージに送信できるため、OLEバージョンでは失われたものはすべて静的に保護する必要があります。 つまり たとえば、あるタイプのプロパティのシーケンスは失われ、すべてのプロパティは配置されますが、ソートはされません。 したがって、プログラムのロジックにより、何も失われていない場所を見つけて、このオブジェクトへのリンクを含む静的変数を作成する必要があります-それらはゴミに送信されず、恥ずかしがり屋です。



ハッカーかハッカーではないのか?



私たちがすべてのプライベートメンバーに簡単に目を向けるとき、純粋な水の反射のまさに概念はハッキングです。 実行時の属性の不変性、それらは型に属しませんが、型は変更できません-すべてのリフレクションと同じハッカーの問題。 すべてが変化しています。 ある種のコレクションを変更することで、誰かが既にそれを参照し、独自のデータ構造を構築しているという事実を考慮することができないことを覚えておく必要があります-何かが落ちるかもしれません。 たとえば、Browsable属性のこの値を変更します-この属性がソースに明示的に記述されていないことを神は禁じています。 この属性は、存在しない場合はデフォルトタイプに割り当てられますが、明示的に登録されていない場合は変更できません。他のすべてのプロパティのすべての参照可能な属性がシャワーされます。 また、実行段階で属性が最初に登録された場所を特定することは非常に困難です。



PropertyDescriptor pd = TypeDescriptor.GetProperties(_pi.DeclaringType)["Name"];

BrowsableAttribute ba =(BrowsableAttribute)pd.Attributes [typeof(BrowsableAttribute)];

FieldInfo isBrowsable = ba.GetType()。GetField( "Browsable"、BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Instance);

isBrowsable.SetValue(ba、false);



All Articles