9

クラス ライブラリに Lookup という静的クラスがあり、このクラスを使用してさまざまな値 (この場合は場所) を検索しています。

これらの値は数百に及ぶ場合があります。私の顧客の 95% はインターネット アクセスのないマシンに私のアプリをインストールするため、私のアプリケーションはインターネット アクセスもデータベースへのアクセスもないと仮定する必要があります。

したがって、これがこれを処理する効率的な方法であるかどうか、およびメソッドが完了したときにオブジェクトを適切に破棄しているかどうかを知りたいです。

コード :

using System;
using System.Collections.Generic;

namespace FunctionLibrary
{
    public static class Lookups
    {
        private static List<Vers> Versions;

        public static string GetVersion(string s)
        {
            string retValue = string.Empty;
            Versions = new List<Vers>();

            try
            {
                if (s.Trim().Length > 0)
                {

                    GetVersions();
                    retValue = Versions.Find(ver => ver.VersionNumber == s).VersionLiteral;

                    if (string.IsNullOrEmpty(retValue))
                    {
                        retValue = string.Format("{0} is an Unknown Version Number", s);
                    }
                }
                else
                {
                    retValue = "No version number supplied";
                }
            }
            catch
            {
                retValue = string.Format("{0} is an Unknown Version Number", s);
            }
            finally
            {
                Versions.Clear();
                Versions = null;
            }
            return retValue;
        }

        private static void GetVersions()
        {
            Versions.Add(new Vers() { VersionNumber = "0000", VersionLiteral = "Location 1" });
            Versions.Add(new Vers() { VersionNumber = "0001", VersionLiteral = "Location 2" });
            Versions.Add(new Vers() { VersionNumber = "0002", VersionLiteral = "Location 3"});
            Versions.Add(new Vers() { VersionNumber = "0003", VersionLiteral = "Location 4"});
            Versions.Add(new Vers() { VersionNumber = "0004", VersionLiteral = "Location 5"});
            Versions.Add(new Vers() { VersionNumber = "0005", VersionLiteral = "Location 6"});
            Versions.Add(new Vers() { VersionNumber = "0006", VersionLiteral = "Location 7"});
            Versions.Add(new Vers() { VersionNumber = "0007", VersionLiteral = "Location 8"});
        }
    }

    public class Vers
    {

        public string VersionLiteral { get; set; }
        public string VersionNumber { get; set; }
   }
}

リストの代わりにディクショナリまたはルックアップを使用する必要があるかどうかも疑問に思っています。このメソッドを複数回呼び出してメモリの問題を引き起こしたくないだけです。

4

3 に答える 3

18

より徹底的な評価のために、codereview.SEを検討することをお勧めします。


List<T>vsDictionary<TKey, TValue>対に関するいくつかの一般的な注意Lookup<TKey, TElement>

他の回答が示しているように、リストの使用はシナリオでひどいものです。これは主に、要素の検索のパフォーマンスが低下するためです。

どちらかを選択するのは難しいことではありませんDictionaryMSDNから私の強調):Lookup

Lookup<TKey, TElement>似ていますDictionary<TKey, TValue>.。違いは
Dictionary<TKey, TValue>キーを単一の値にマップするのに対し、 Lookup<TKey, TElement>キーを値のコレクションにマップすることです。

を実装するオブジェクトをLookup<TKey, TElement>呼び出すことにより、のインスタンスを作成できます。ToLookupIEnumerable<T>.

キーを単一の値にマップするだけでよいので、aDictionaryが正しい選択です。


以前に受け入れられた答えは正しい方向への一歩ですが、それでもいくつかの重要な問題があります(編集:これらの問題はその後解決されました)

文字列は不変です: s.Trim()変更されません—後で使用する場合に必要sな新しいstring意味を返しますs = s.Trim()s

静的クラスはインスタンスコンストラクターを持つことができませんpublic Lookups()あるべきですstatic Lookups()(静的コンストラクターはアクセス修飾子を持つことはできません—もちろん)。

空の文字列/エラーメッセージを文字列として返さないでください

それは素晴らしいデバッグの頭痛の種になるでしょう。エラー文字列を渡す代わりに例外を使用する必要があります—そして辞書に特定のバージョンが含まれているかどうかをチェックするメソッドを提供する必要があります!VersionExists

変更された、より安全な例

FormatExceptionこれにより、パラメータが空、null、または空白の場合にがスローされます。バージョンが存在しない場合は、DictionaryがスローさKeyNotFoundExceptionれます—デバッグよりも少し便利string.Emptyですよね。

public static class Lookups
{
    private static Dictionary<string, Vers> Versions;

    static Lookups()
    {
        Versions = new Dictionary<string, Vers>
        {
            {"0000", new Vers {VersionNumber = "0000", VersionLiteral = "Location 1"}},
            {"0001", new Vers {VersionNumber = "0001", VersionLiteral = "Location 2"}},
            {"0002", new Vers {VersionNumber = "0002", VersionLiteral = "Location 3"}},
            {"0003", new Vers {VersionNumber = "0003", VersionLiteral = "Location 4"}},
            {"0004", new Vers {VersionNumber = "0004", VersionLiteral = "Location 5"}},
            {"0005", new Vers {VersionNumber = "0005", VersionLiteral = "Location 6"}},
            {"0006", new Vers {VersionNumber = "0006", VersionLiteral = "Location 7"}},
            {"0007", new Vers {VersionNumber = "0007", VersionLiteral = "Location 8"}}
        };
    }

    public static bool VersionExists(string versionNumber)
    {
        return Versions.ContainsKey(versionNumber);
    }

    public static string GetVersion(string s)
    {
        if (string.IsNullOrWhiteSpace(s)) 
            throw new FormatException("Empty version number!");
        return Versions[s.Trim()].VersionLiteral;
    }
}
于 2012-07-22T07:35:02.380 に答える
3

それを試してください:

using System;
using System.Collections.Generic;

namespace FunctionLibrary
{
public static class Lookups
{
    private static Dictionary<string, Vers> Versions = new Dictionary<string, Vers>();

    static Lookups() //Static constructor
    {
        CreateVesions();
    }

    public static string GetVersion(string s)
    {
        string retValue = string.Empty;

                    s = s.Trim();

        if (s.Length > 0 && Versions.ContainsKey(s))
        {
            retValue = Versions[s].VersionLiteral;
        }

        if (string.IsNullOrEmpty(retValue))
        {
            retValue = string.Format("{0} is an Unknown Version Number", s);
        }

        return retValue;
    }

    private static void CreateVesions()
    {
        Versions["0000"] = new Vers() { VersionNumber = "0000", VersionLiteral = "Location 1" };
        Versions["0001"] = new Vers() { VersionNumber = "0001", VersionLiteral = "Location 2" };
        Versions["0002"] = new Vers() { VersionNumber = "0002", VersionLiteral = "Location 3" };
        Versions["0003"] = new Vers() { VersionNumber = "0003", VersionLiteral = "Location 4" };
        Versions["0004"] = new Vers() { VersionNumber = "0004", VersionLiteral = "Location 5" };
        Versions["0005"] = new Vers() { VersionNumber = "0005", VersionLiteral = "Location 6" };
        Versions["0006"] = new Vers() { VersionNumber = "0006", VersionLiteral = "Location 7" };
        Versions["0007"] = new Vers() { VersionNumber = "0007", VersionLiteral = "Location 8" };
    }
}

public class Vers
{

    public string VersionLiteral { get; set; }
    public string VersionNumber { get; set; }
}

}

それによってあなたは得る:

  1. 値を一度だけ初期化します
  2. ディクショナリを使用してバージョンを検索するパフォーマンスの向上
  3. GetVersionメソッド内のコードが少ない
于 2012-07-22T06:36:39.263 に答える
2

この状況で List を使用すると、非常に非効率になります。この場合、アプリケーションは途方もなく遅くなります。

辞書の検索は大いに役立ちます。

それらの違いは、ディクショナリが 1 つしか受け入れない場合、ルックアップでは特定のキーに対して複数の値を持つことができることです。

したがって、あなたのケースで VersionNumber が一意の場合は Dictionary を使用し、それ以外の場合は Lookup を使用します。

リストをディクショナリまたはルックアップに一度変換するだけです。

var versionsDictionary = versionsList
                             .ToDictionary(x => x.VersionNumber);

したがって、一度 (おそらくアプリの読み込み時) 実行すると、どこでも使用できます。

var myVersion = versionsDictionary[givenNumber];
Console.WriteLine(myVersion.VersionLiteral);

繰り返しますが、ルックアップが必要な場合は、ToDictionary を ToLookup に置き換えてください ;)

于 2012-07-22T06:52:06.873 に答える