2009-08-27 7 views
11

私のチームの1人は、最近、マトリックスの興味深い欠点に遭遇しました。誰かがこれを説明するのを助けることができればそれはすばらしいだろう。それはおそらく説明するのは複雑なので、私と一緒にいてください。IIS7での奇妙な64/32ビットGUIDの問題

私たちはASP.Netアプリケーションを構築しています。その中には単純な「if」文があります。

Guid adminId = Guid.Empty; 
if (mRoles.Contains("Admin")) 
{ 
    adminId = mUserId; 
} 

(mRolesが一覧で、「管理者」が含まれている場合)

これは(すなわちadminIdにはmUserIdが割り当てられている)期待と同じように動作します。ただし、以下の三項演算子を使用するように書き直された場合、それはありません! (adminIDにはGuid Emptyが割り当てられます)!

Guid adminId = mRoles.Contains("Admin") ? mUserId : Guid.Empty; 

これは64ビットマシン(IIS7/64ビットVistaの場合)にあり、発見された開発者 ...次のように彼は「既定のアプリケーションプール」>「詳細の下にIISでの彼の設定を変更した場合設定 "チェック"有効にする32ビットアプリケーションを有効にする "今すぐ両方のステートメントが動作します!

これは、Guidがクラスではなく構造体であり、値が何らかの形で64ビットプロセスでオフセットされている可能性があると考えられます。なぜ最初の単純なif文の動作を説明するかもしれない http://www.mail-archive.com/[email protected]/msg00164.html 私は問題はこれに類似している疑いがある

...。 (adminId変数を作成するとポインターが作成される可能性がありますが、3進演算子は生成されません)

誰かがこれを踏まえれば、それは素晴らしいものになるでしょう。 互換性のバグですか?三項演算子と構造体を組み合わせることについての誤解?

ありがとうございました。

UPDATE

一緒に簡単なアプリケーションを入れて、完全に新しいプロジェクトでそれを再現することはできませんので、GUIDがより何か他のものでなければなりません。

//作品は

Guid adminId = true ? mUserId : Guid.Empty; 

//動作しない(たとえトン==真!!!! ???)(adminIdにまでmUserIdを割り当て)

bool t = (mRoles.Contains("TenantAdmin"); 
Guid adminId = t ? mUserId : Guid.Empty; 

私たちは」だと思いますこれで描画ボードに戻ります。あなたの助けをお寄せいただきありがとうございました。私たちが何かを得ることができれば、私はここに再び投稿します

多分あまり明確ではなかったのは、mRolesがタイプ文字列の汎用リストではないということだけでした。これは文字列[]であり、Contains()メソッドはLINQsの拡張メソッドです。違いがあれば、その理由は分かりません。

我々はIL見てきたし、それが正しい(そして今断続的に動作します!)UPDATE 2

は、私たちが発見したと、デフォルトのアプリケーションプールは、より多くのアプリケーションをロードするとき、それが再び失敗し始めていることです。私たちが考えることができる唯一の他のものは、これらの他のアプリケーションの中には、アプリケーションに何らかの形で干渉している管理されていないコードが含まれている可能性があるということです。

+2

まったく新しいプロジェクトのいくつかの単純な行で動作を複製できますか? –

+0

+1。完全に分散する – AnthonyWJones

+1

コンパイル中に異なる設定が有効なときに生成されるILを比較します。 – AakashM

答えて

0

これは、IISのバグと同じapplcationプールに走っ別のアプリケーションでアンマネージコードの塊のように見えます。私たちは今のところそれを取り巻き、パートナーシップを通じてマイクロソフトと提携していきます。それが解決されると私はあなたに知らせるためにここにポストするでしょう。

ありがとうございました。

0

三項演算子からの戻り値がGuidであることを代入演算子に具体的に伝えるのに役立つでしょうか?

Guid adminId = (Guid)(mRoles.Contains("Admin") ? mUserId : Guid.Empty); 

ちょうど野生の推測...

+0

Nope。まだ動かない。 – ChrisV

+0

同様の野生の推測 - これは評価の順序ですか?あなたが条件付きとして代入を解析していないことを確認するために、三項ステートメントの周りに括弧を入れてみてください。 – mpez0

0

ちょうど64ビットマシンがmUserIdがあると考えてどのようなタイプの不思議?おそらくガイドではありません。

+0

確かにSystem.Guid :-( – ChrisV

+0

mUserIdがGUIDでない場合、戻り値の型を判別できないというコンパイラエラーが発生します。 – Mark

0

私は確信していません。私はテナリ操作を使用する場合、両方のブランチを実行する必要があると思いますが、GUIDでは2つのGUIDがいくつかの方法で評価される可能性があります。

1

三項演算子を括弧で括ってみてください。

Guid adminId = t ? mUserId : Guid.Empty; 

間違った順序でコンパイルされた:

は、私たちはあなたのようなコードはここで同様の問題があった

Guid adminId = (t ? mUserId : Guid.Empty); 
:順序を指定するには、括弧を追加

(Guid adminId = t) ? mUserId : Guid.Empty; 

はそれを修正

.NET Reflectorでコンパイルしたコードを調べることで、何をしているのか分かりました。どんな理由であれ、mUserIdが内部で64ビットのオペレーティングシステムの下では異なるタイプとして認識され、かつ明示的にキャストした場合には役立つだろう、あれば

Guid adminId = mRoles.Contains("Admin") ? (Guid)mUserId : Guid.Empty; 

興味があるだけ:

0

では、次を試してみました。次はまた、オプションであるかもしれない:

Guid adminId = mRoles.Contains("Admin") ? new Guid(mUserId.ToByteArray()) : Guid.Empty;