問題タブ [il]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c# - 動的に生成されたILでの値型変換
更新
1年以上後、私はついにこの動作の原因に気づきました。基本的に、オブジェクトは、ボックス化されたものとは異なるタイプにボックス化解除することはできません(そのタイプが宛先タイプにキャストまたは変換された場合でも)。正しいタイプがわからない場合は、何らかの方法でオブジェクトを検出する必要があります。割り当ては完全に有効である可能性がありますが、これが自動的に行われることは現実的ではありません。たとえば、バイトがInt64に収まる場合でも、バイトをlongとしてアンボックス化することはできません。バイトをバイトとしてボックス化解除してから、キャストする必要があります。
それを行うのに十分な情報がない場合は、別の手段を使用する必要があります(以下に示すように)。
元の問題
私はILと協力して、一般的にリフレクションで処理される多くのタスクのパフォーマンスを向上させています。これを達成するために、私はDynamicMethod
クラスを多用しています。
オブジェクトにプロパティを設定するための動的メソッドを作成しました。これにより、開発者は名前のみに基づいてその場でプロパティを設定できます。これは、データベースからビジネスオブジェクトへのレコードのロードなどのタスクに最適です。
しかし、私は1つの(おそらく単純な)ことに固執しています。値型をさらに大きな型から小さな型に変換することです(たとえば、バイトの値をInt32に入れるなど)。
これが、動的プロパティセッターを作成するために使用しているメソッドです。IL生成部分以外はすべて削除したことに注意してください。
IL生成時にプロパティタイプを確認し、変換を使用してみOpCodes
ました。それにもかかわらず、コードはまだ。をスローしInvalidCastException
ます。この例は、スタック上の値が割り当てられているプロパティのタイプと一致するように変換されることを(私が思うに)確認する必要があることを示しています。
また、次のような値型のボックス化を解除する前または後にキャストを試みました。
Convert
ILを作成してオブジェクトと呼び出しを動的に作成できると思いますChangeType()
が、ほとんどの場合これが問題にならない場合は無駄に思えます(型が一致する場合は問題ありません)。
問題を要約すると、動的に生成されたメソッドに値の型を渡すと、割り当てられているプロパティの型と完全に一致しない場合、宛先の型のサイズが大きくても、InvalidCastExceptionがスローされます。ソースタイプより。私が試した型変換は機能しません。
質問に答えるためにさらに情報が必要な場合は、私に知らせてください。
編集:@ JeffN825は、コンバージョンを見て正しい方向に進んでいました。System.Convertクラスを検討しましたが、高すぎるとして除外しました。ただし、宛先タイプが手元にあれば、そのタイプに適したメソッドのみを呼び出すルーチンを作成できます。これ(テストに基づく)は比較的安いようです。結果のコードは次のようになります。
確かに、これは巨大なif / elseステートメント(すべてのタイプが実装されている場合)になりますが、BCLの動作と同じであり、このチェックはILが生成されたときにのみ実行され、すべての呼び出しでは実行されません。したがって、正しいConvertメソッドを選択し、そのメソッドへの呼び出しをコンパイルします。
オブジェクトのメソッドは静的OpCodes.Call
であるため、必須ではなくOpCodes.Callvirt
、必須であることに注意してください。Convert
パフォーマンスは立派です。カジュアルテストでは、動的に生成されたsetメソッドへの1,000,000回の呼び出しに約40ミリ秒かかることが示されています。反射から一体を打ち負かします。
c# - プロダクションで使用するために ILAsm ファイルから .property ステートメントを削除しても問題ありませんか?
ILAsm ファイルの変更に基づいた難読化プログラムにまだ取り組んでいます。(参照。難読化すべきではない C# メソッド名はどれですか? )
ILAsm コードを見ると、.property ステートメントは何にも (少なくともプログラムの実行には) 使用されていないという印象を受けます。Visual Studio のメタデータを提供するためだけに存在すると考えているのは正しいですか? その場合、ILAsm コードが Visual Studio で使用されることのない製品モジュールを生成するためにのみ使用される場合、単純にそれらを削除しても問題ありませんか?
.net - int をキャッチする方法
IL を使用して Int32 をスローし、キャッチしています。これはただの好奇心からです。私は何も達成しようとはしていません。そのため、int の代わりに例外をスローするように言わないでください。
これは機能しません。「In Object catch」という文字列が表示されますが、箱から出そうとすると System.InvalidCastException: Specified cast is not valid が発生します。スローされたものの値を取得するにはどうすればよいですか?
c# - IL: ldfld 対 ldflda
私は、IL レベルでターゲット アセンブリを操作する必要がある、Mono.Cecil を使用して小さな IL ウィービング アプリケーションを作成しています。
私の質問は非常に単純ですが、それでもこの問題は非常に紛らわしいと思います。との指示の実際的な違いは何ですか?ldfld
ldflda
msdn に相談したところldfld
、フィールドの値をフェッチしている間に、フィールドldflda
のアドレスを取得しているようです。わかりました...しかし、これはどういう意味ですか?前者は値型 (および文字列) に使用され、後者は参照型に使用されると最初は思っていましたが、C# スニペットをコンパイルして Reflector で確認したところ、間違っていることがわかりました。
C# コンパイラがldflda
の代わりに出力するときに明確なパターンを見つけることができませんでしldfld
た。検索しても、これを説明する記事は見つかりませんでした。ldflda
では、代わりにいつ使用するのldfld
ですか?
どんな助けでも大歓迎です。
c# - C# で新しい型を生成する方法
実行時に新しい型を生成したいのです。基本的に、次のようなタイプを作成したいと思います。
一部の型はユーザー/DB の入力によって異なるため、実行時に型を作成する以外の方法では実現できません。もっと複雑なこともありますが、質問を簡単にしたかったので、ここでは本質的な質問だけをしています. ここに表示されているものよりも多くの生成を行う必要があります。
を使用するのはクールだと思っていましたがReflection.Emit
、コードを生成してすべてをメモリ内でコンパイルする方が簡単かもしれないことに気付きました。どちらが良いか知っている人はいますか?これらのいずれかを行う方法の例を本当に見たいです。
.net - .maxstack1によって割り当てられた1スタックのサイズ
私が言うとき.maxstack 1
、それはどのように機能しますか?任意のデータ型をスタックにプッシュできますか?スタックのサイズはどのように決定されますか。それは時期尚早に行われるのですか、それとも実行時に行われますか?
編集1:スタックに引数を1つだけプッシュした場合でも、その引数のメモリ割り当てはどのように決定されますか?そのデータ型はコンパイル時または実行時に識別されますか?
c# - Dictionary に値を追加する C# IL コード
DataRecord
を受け取り、データを特定のタイプのオブジェクトにマップする動的メソッドがあります。
オブジェクトには、Dictionary<string,object>
バインドできない DataRecord のプロパティを保持する型のディクショナリがあります。
ただし、これらを辞書に追加する方法を理解できないようです。
辞書を呼び出さなければならないことはわかっていますEmit(OpCodes.Callvirt, addMethod)
が、何を試しても、それを機能させる方法がわかりません。
c# - Mono.Cecilを使用してByReferenceTypeからジェネリックパラメーターを取得します
次のようなパラメータを取得するメソッドがあります。
Cecilを使用してパラメーターを列挙すると、ByReferenceTypeが生成されます。パラメータを逆参照しようとしてGetElementType()を呼び出すと、フルネームのTypeReferenceが返されます。
どういうわけか、それはジェネリックパラメータを失い、もはやGenericInstanceTypeではありません。
byrefパラメーターを適切に逆参照して、実際の汎用インスタンスタイプを取得するにはどうすればよいですか?
c# - C#で生成された++演算子のIL-プレフィックス/ポストフィックス表記が高速である場合と理由
この質問は、インクリメント演算子とプレフィックス/ポストフィックス表記の速度の違いに関するものなので、Eric Lippertがそれを発見して私を怒らせないように、質問を非常に注意深く説明します。
(私が尋ねている理由の詳細と詳細については、http://www.codeproject.com/KB/cs/FastLessCSharpIteration.aspx?msg = 3899456#xx3899456xx /を参照してください)
私は次のように4つのコードスニペットを持っています:-
(1)個別、プレフィックス:
(2)個別、後置:
(3)インデクサー、Postfix:
(4)インデクサー、プレフィックス:
私がやろうとしていたのは、このコンテキストでプレフィックス表記とポストフィックス表記の間にパフォーマンスの違いがあるかどうか(つまり、ローカル変数が揮発性ではない、別のスレッドから変更できないなど)があるかどうかを証明/反証することでした。 。
速度テストはそれを示しました:
(1)と(2)は同じ速度で動作します。
(3)と(4)は同じ速度で動作します。
(3)/(4)は(1)/(2)よりも約27%遅くなります。
したがって、後置記法自体よりも前置記法を選択することによるパフォーマンス上の利点はないと結論付けています。ただし、操作の結果を実際に使用すると、コードが単純に破棄される場合よりもコードが遅くなります。
次に、Reflectorを使用して生成されたILを調べたところ、次のことがわかりました。
ILバイト数はすべての場合で同じです。
.maxstackは4から6の間で変化しましたが、これは検証目的でのみ使用されるため、パフォーマンスには関係ないと思います。
(1)と(2)はまったく同じILを生成したので、タイミングが同じであることは当然です。したがって、(1)は無視できます。
(3)と(4)は、非常によく似たコードを生成しました。唯一の関連する違いは、操作の結果を説明するためのdupオペコードの配置です。繰り返しますが、タイミングが同じであることについては驚くことではありません。
そこで、(2)と(3)を比較して、速度の違いを説明できるものを見つけました。
(2)ldloc.0 opを2回使用します(1回はインデクサーの一部として、その後は増分の一部として)。
(3)ldloc.0を使用し、直後にdupopを使用しました。
したがって、(1)(および(2))のjの増分に関連するILは次のとおりです。
(3)次のようになります。
(4)は次のようになります。
今(ついに!)質問に:
JITコンパイラはldloc.0/ldc.i4.1/add/stloc.0
、ローカル変数を1ずつインクリメントするだけのパターンを認識し、それを最適化するため、(2)は高速ですか?(そして、dup
(3)と(4)の存在はそのパターンを壊すので、最適化は失われます)
そして補足:これが本当なら、少なくとも(3)については、dup
を別のものに置き換えてldloc.0
そのパターンを再導入しませんか?
c# - .Net プラットフォーム用の IL の生成
私は C# で小さなコンパイラを作成しており、.Net プラットフォーム用の IL 命令を生成する予定ですSystem.Reflection.Emit
。System.Reflection.Emit
私の質問は、製品コンパイラ用の IL の生成 に使用することをお勧めします。
プロダクション コンパイラ用の IL の生成に使用することが推奨されない場合System.Reflection.Emit
、その目的のための代替ライブラリ/ツールはありますか?