2016-12-13 6 views
0

パフォーマンス面では、文字列配列の代わりに列挙型を使用する方が効率的ですか?列挙型のメソッドと文字列の比較

特定のメソッドIsDefinedをテストし、文字列配列内のマッチアップをチェックすることにしました。私はそれぞれのランタイムをテストするためにStopwatchのオブジェクトを作成しました。

enum Color : byte { red, blue, green } 

内部の主要:

string[] colArr = new string[] { "red", "blue", "green" }; 
string input = "green"; 
Stopwatch s1 = new Stopwatch(); 
int loopIterations = 0; 

s1.Restart(); 
while (loopIterations++ < 100000000) 
    foreach (var blah in colArr) 
     if (blah == input) 
      break; 
s1.Stop(); 
Console.WriteLine("Runtime for foreach loop: {0}", s1.Elapsed); 

loopIterations = 0; 
s1.Restart(); 
while (loopIterations++ < 100000000) 
    if (Enum.IsDefined(typeof(Color), input)) 
     continue; 
s1.Stop(); 
Console.WriteLine("Runtime for IsDefined method returned value: {0}", s1.Elapsed); 

そして、私の出力は次のようになります。

Runtime for foreach loop: 00:00:01.4862817 
Runtime for IsDefined method returned value: 00:00:09.3421654 
Press any key to continue . . . 

クラスのメインの外に列挙型を定義

:以下
コード、だから私は、もし私が書いたコードが、愚かなものではない、あるいは物事 - それらの数字は正常であり、もしそうであれば、文字列配列を使用するのに好ましいenumをどのような方法で使用していますか?

+1

どちらも独自の目的を持っています。開発者に優しいAPIにはenumを使用し、ユーザー入力には文字列を使用します。あなたの研究は何を示しましたか? – CodeCaster

+3

あなたは文字列のようにenumを使用していますが、それはあまり効率的ではありません。代わりに 'Color'として保存してください。例:' Color input = Color.green; '。次に、それが存在するかどうかを確認する必要はありません。 –

+1

'Enum.IsDefined(typeof(Color)、input)'の呼び出しはおそらく文字列を解析してアンボクシングする必要があるので、計算を偽装します。より適切な結果を得るには、 'Enum.GetValues'を' foreach(var blah in colArr) 'と同等のものとして使うことができます。 – HimBromBeere

答えて

2

パフォーマンスよりも、列挙型を文字列に使用する大きな理由は、コードの保守性です。たとえば、「すべての参照をColor.redに見つける」ことは、ビジュアルスタジオで数回のクリックで行うことができます。文字列を見つけようとするのは簡単ではありません。常に文字列を入力するのも間違いやすいです。両方の問題は定数を使用することによって幾分緩和することができますが、enumを使用する方が簡単です。

列挙型は、一定の整数値と見なすことができます。これは、パフォーマンスがよく、フラグ(マスク)を使用するなどの利点があります。 intを比較すると文字列を比較するよりも速くなりますが、ここでは起こりません。ほとんどの場合、特定の値に対して何かをしたいのですが、if(someString == "red")if(someColVal == Color.red)をテストすることができます。この場合、後者のほうが速いはずです。

値が列挙型に存在するかどうかを調べるには、Enum.IsDefinedを使用すると速度が遅くなる可能性がありますが、この関数ではこのループで毎回列挙型の値をルックアップする必要があります。 一方、最初のテストにはあらかじめ定義された配列があります。あなたの最初のテストのパフォーマンスで厳密な比較のために、あなたのような何かを行うことができます:述べたように、値がenumに存在する場合に見つけることが、通常、その主な機能はありませんが

var colvalues = Enum.GetValues(typeof(Color)).Cast<Color>().ToArray(); // or hardcode: var colvalues = new[]{Color.red, Color.blue, Color.green}; 
var colinput = Color.red; 
while (loopIterations++ < 100000000) 
    foreach (var blah in colvalues) 
     if (blah == colinput) 
      break; 

を(主にそれがためにチェックするために使われています特定の値)。ほとんどの入力になります。しかし、値がユーザ入力に関するコメントを見て、予想されるようなマスクチェック又は>などの範囲、>=<又は<=

編集にあるかどうかを確認する他の方法を可能にする整数ベースです例えば、ユーザーにメニューが表示されます。コンソール環境では、そのメニューは列挙型の数で構築することができます。 例えば、列挙enum Color : byte { red = 1, blue, green }、メニュー 1.赤2.青 3.緑色

ユーザ入力は整数であろう。一方、入力が必要な場合は、IsDefinedは値を再入力する必要がなくなり、使いやすさに優れています。パフォーマンスのために名前のようなものでバッファリングすることができますvar colvalues = Enum.GetNames(typeof(Color)).ToArray();

+0

名前:TBH、私はマスクを使うことが利益だとは言いません。 IMHOは維持することは容易ではなく、想定されるメリットよりも多くのコードの混乱やエラーにつながります。記憶に制約された1990年代にはおそらく意味がありましたが、今日の世界では、「選択された」列挙型をコレクションとして維持する方が良いでしょう。 – code4life

+0

@ code4life個人的に私はマスク付きのフラグenumを愛しています。 (単一の値の場合、色としてはもちろん無意味です)。メモリの制約からではなく、簡単に値を追加または削除できます。例えばborder-enumプロパティ: 'someClass.Border | = Border.Left'は、既に設定されているかどうかにかかわらず、左境界線を設定します。あなたがコレクションでそれを行う場合、値がすでにコレクションの中にあるかどうかをチェックするために余分なコードを追加しない限り無限のエントリを得ることができます –

+0

ありがとう:)答えは非常に明確で徹底的です。 +1 –

1

enumの通常の使用は、論理状態または限られた範囲のオプションを表すことです。製品は今までに3色しか出てこなかった。このような場合に文字列を使用して色を表現するには、2つの欠点があります。コードのどこかで色の名前を間違えてしまい、バグの追跡が困難になることがあります。文字列の比較は、基本的に整数を比較しているenumを比較するよりも本質的に遅いです。

IsDefined()はタイプリフレクションを使用するため、ストレート文字列比較よりも遅くする必要があります。列挙型を文字列に変換したり、文字列から変換したい場合があります。通常、構成の保存や復元などの入出力を行うときです。それは遅いですが、入出力は通常、ストレージメディアやネットワークの遅さによって支配されているため、めったに大きな問題ではありません。

+0

私はそれが大したことではないことを理解していますが、重要なことは、文字列を使用した入力操作では、パフォーマンスが向上した場合にはパフォーマンスが向上することです。私の質問のコメントに書いたように、ユーザーは色の名前を入力するように求められ、プログラムは一致するものを探します。これらのタイプのジョブでは、文字列配列を使用するのが望ましいです。 –

+0

@Chenを使用すると、文字列をenum ** once **に変換してからIsDefinedを使用できます。それはIsDefinedが内部で行うことです。 stringをenumに変換して比較を開始します。これをループに入れると、変換もループに含まれます。だからあなたのベンチマークは間違っています。文字列を列挙型に変換するオーバーヘッドを測定しているからです。 –

+0

_これらのタイプのジョブでは、文字列配列を使用するのが望ましいです。いいえ。コードの可読性とパフォーマンスの間にトレードオフがあります。文字列配列を使用すると、コードのメンテナンス性が低下し、読みやすくなります。 @Chen –