9

IsLittleEndianでフィールドを発見したときはとてもうれしかったBitConverterです。もちろんそこにあるはずで、好きなエンディアンを指定できるはずだと思いました。さて、私の幸せは長くは続きませんでした。フィールドを設定する方法がないことがわかるまで、しばらく時間を費やしました。フィールドはであり、静的コンストラクターでreadonlyのみ設定されます。true

static BitConverter()
{
    IsLittleEndian = true;
}

フィールドが実際にコードで使用されているのは面白いです。たとえば、ToInt32メソッドの実装は次のようになります。

if (IsLittleEndian)
{
     return (((numRef[0] | (numRef[1] << 8)) | (numRef[2] << 0x10)) | (numRef[3] << 0x18));
}
return ((((numRef[0] << 0x18) | (numRef[1] << 0x10)) | (numRef[2] << 8)) | numRef[3]);

ToInt32そのため、リトルエンディアンとビッグエンディアンの両方を完全に処理できるようです。

私の質問は、FCL に既に実装されている非常に便利なコードがあるのに、それを使用する方法がないのはなぜですか (もちろん、リフレクションをいじり始めない限り)。一部の開発者が締め切りに間に合わず、仕事を中途半端に放置しただけなのでしょうか? そうだとしても、なぜコードは利用できないのに、フィールドは利用できるのでしょうか? これには正当な理由があることを願っています。

私は自分自身を明確にしたい。ビッグエンディアンの値を処理する方法についての解決策は必要ありません。私には解決策があります。解決策は実際に私の質問に示されています。

4

7 に答える 7

6

残念ながら、このIsLittleEndianフィールドはあなたに通知するためだけのものです。しかし、Jon Skeets MiscUtil ライブラリには、リトル エンディアンとビッグ エンディアンをサポートする優れた EndianBitConverter があります。エンディアン対応の BinaryWriter/-Reader クラスもあります。

リンクは次のとおりです。 http://www.yoda.arachsys.com/csharp/miscutil/

編集:申し訳ありませんが、より良い説明はありません。これはフレームワークに含まれているべきだったと思います。コードは現在そこにあると思います。そのため、Converter を別のアーキテクチャに簡単に移植できます。

しかし、その機能を公開することは、単にフィールドを公開するよりも少し複雑です。コンバーターは静的であるため、フラグを変更するとグローバル状態が効果的に変更され、マルチスレッドのシナリオでは悲惨な結果になります。おそらく、インスタンス化してローカルで使用できる 2 つの BitConverter オブジェクトを提供することです (これが MiscUtil の機能です)。これには追加のクラスやインターフェースが必要になるため、締め切りの問題であり、当分の間ドロップされた可能性があります。しばらくしてから追加されることを期待しましょう。

于 2011-06-20T04:10:23.620 に答える
5

まず、クラスがローカル プロセッサ専用のBitConverterビット変換用に特別に設計されていることを確認しましょう。そのため、は読み取り専用です。その結果、ローカル プロセッサがリトル エンディアンの場合、ビッグ エンディアンへの変換またはビッグ エンディアンからの変換はサポートされません。IsLittleEndian

一般的なエンディアンのサポートを省略する理由はわかりませんが、私にとって最も論理的な理由はパフォーマンスです。本来の目的 (ネイティブ プロセッサのエンディアンとの間の変換) のためにフレームワーク全体で広く使用されるクラスは、可能な限りパフォーマンスが高くなければなりません。クラスの一般性を制限することで、処理する必要のあるケースを制限することでパフォーマンスが向上します。リトルエンディアンのみをサポートすることで、測定速度が向上する可能性があります。

では、問題の核心に行きましょう。クラスの全体的な設計が 1 つだけをサポートすることを意図している場合、作成者はなぜリトルエンディアンとビッグ エンディアンの両方を処理するコードを含めるのでしょうか?

繰り返しますが、推測することしかできません。しかし、その答えは次の 2 つの観察結果にある可能性があります。

  • 参照する逆アセンブルされたコードIsLittleEndian は、パフォーマンスに関して重要でないケースです
  • 移植可能なコードを書くことは、それがパフォーマンスに影響を及ぼさないのであれば、優れたソフトウェア エンジニアリングです

メソッドからコピーしたコードが重要ではない理由は、それがunaligned memoryToInt32にのみ使用されるためです。99% のコード パスは、直接安全でないビットの "memcpy" です。

アラインされていないメモリからの変換が発生する場合でも、それを処理するコードは生のメソッドよりも桁違いに効率的ではありません。したがって、余分な条件によってパフォーマンスが実際に損なわれることはありません。

正味の結果は次のとおりです。

  • BitConverterクラスは、その限られた目的のために可能な限り効率的です
  • のソースコードBitConverterは、ビッグエンディアン プロセッサ アーキテクチャに移植可能です。
于 2011-06-30T04:28:33.787 に答える
5

答えは、BitConverter クラスのリファレンス ソースを見ることにあります。

関連する抜粋は次のとおりです。

        // This field indicates the "endianess" of the architecture.
        // The value is set to true if the architecture is
        // little endian; false if it is big endian.
#if BIGENDIAN
        public static readonly bool IsLittleEndian /* = false */;
#else
        public static readonly bool IsLittleEndian = true;
#endif

フレームワークの特定のバージョンがコンパイルされるアーキテクチャのエンディアンは変更されないため、フラグはプリプロセッサ ディレクティブによって固定されています。

于 2014-07-23T11:39:02.630 に答える
1

MSDN のドキュメントIsLittleEndianによると、アーキテクチャがリトル エンディアンかビッグ エンディアンかをユーザー (プログラムまたは BitConverter クラス) に通知するだけです。それ以外の用途があるとは思いません。

于 2011-06-20T03:33:00.563 に答える
0

のすべてのバージョンがリトルエンディアンであるためtrue、可能性なしに設定したと確信しています。falseWindows

さて、それ以外の値にif (IsLittleEndian)決して設定されないクラスでそれらが実行されているという問題は、おそらく念のためのシナリオです。このようにすると、ビッグ エンディアン用に .NET BCL をコンパイルする必要がある場合でも、新しいコードを記述する必要がなく、単純な/を 1 つの割り当てで十分に処理できます。IsLittleEndiantrue#if#else

Mono はfalse、一部のオペレーティング システムとアーキテクチャ用に設定されているに違いありません。

編集:そして私は正しかった。Mono は次のことを行います。技術的には、著作権の問題により Mono ですべてを別の方法で記述しなければならなかったことを除けば、他のコードに追加する必要はありません。

public static readonly bool IsLittleEndian = AmILittleEndian ();

static unsafe bool AmILittleEndian ()
{
  // binary representations of 1.0:
  // big endian: 3f f0 00 00 00 00 00 00
  // little endian: 00 00 00 00 00 00 f0 3f
  // arm fpa little endian: 00 00 f0 3f 00 00 00 00
  double d = 1.0;
  byte *b = (byte*)&d;
  return (b [0] == 0);
}
于 2011-06-20T04:37:25.023 に答える
0

http://snipplr.com/view/15179/adapt-systembitconverter-to-handle-big-endian-network-byte-ordering-in-order-to-create-number-types-from-bytes-and-viceversaを参照してください/エンディアンネスを設定できる実装が必要な場合。

于 2011-06-20T04:02:30.307 に答える
0

アーキテクチャ タイプに基づいて内部的に設定されます。

ドキュメントから:

「さまざまなコンピューター アーキテクチャは、さまざまなバイト順序を使用してデータを格納します。「ビッグ エンディアン」は、最上位バイトが単語の左端にあることを意味します。「リトルエンディアン」は、最上位バイトが単語の右端にあることを意味します。

編集:

これは、c# チームによる設計上の決定です。この関数は、両方のタイプのシステムで使用できるため、両方のタイプから変換できます。それ以外の場合は、開発者が変換する必要があります。

「...BitConverter のすべてのメソッドは、SYSTEM エンディアン順でバイト配列を受け入れたり返したりします...」

int i = BitConverter.ToInt32(byte[] inputdata);
(manipulate i)
return BitConverter.GetBytes(i);

「データがアプリケーションの範囲外に出ない場合、これは実際にうまく機能します。」

詳細については、この記事を参照してください

于 2011-06-20T03:32:31.487 に答える