9

我的类库中有一个名为 Lookup 的静态类,我正在使用这个类来查找不同的值(在本例中为 Locations)。

这些值可以达到数百个。由于 95% 的客户将我的应用程序安装在无法访问 Internet 的机器上,因此我不得不假设我的应用程序无法访问 Internet 或访问数据库。

所以我想知道这是否是一种有效的处理方法,以及在方法完成时我是否正确地处理了对象:

代码 :

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

For a more thorough assessment, you might want to consider codereview.SE.


Some general notes on List<T> vs Dictionary<TKey, TValue> vs Lookup<TKey, TElement>

As other answers have shown, using a List is terrible in your scenario, mainly because looking up elements will have bad performance.

Choosing between Dictionary and Lookup isn't hard (from MSDN, emphasis mine):

A Lookup<TKey, TElement> resembles a Dictionary<TKey, TValue>. The difference is
that a Dictionary<TKey, TValue> maps keys to single values, whereas a Lookup<TKey, TElement> maps keys to collections of values.

You can create an instance of a Lookup<TKey, TElement> by calling ToLookup on an object that implements IEnumerable<T>.

Since you will only need to map keys to single values, a Dictionary is the right choice.


The previously accepted answer is a step in the right direction but still gets several key things wrong (edit: these problems have since been resolved).

Strings are immutable: s.Trim() will not change s — it will return a new string meaning you need to s = s.Trim() if you are using to s afterwards, which you are.

A static class can't have an instance constructor: public Lookups() should be static Lookups() (static constructors are not allowed to have access modifiers — of course).

Don't return an empty string / an error message as a string!

That's going to end up as a wonderful debugging headache. You should be using Exceptions instead of passing error strings around — and you should provide a VersionExists method to check if your dictionary contains a certain version!

Modified, safer example

This will throw a FormatException if the parameter is empty, null or whitespace. In the event that the version doesn't exist, the Dictionary will throw a KeyNotFoundException — a bit more helpful for debugging than string.Empty, don't you think?

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. Less code in GetVersion method
于 2012-07-22T06:36:39.263 回答
2

Using List in this situation leads to HUGE inefficiency. Your application will be ridiculously slow in this case.

Lookup of Dictionary will help A LOT.

The difference between them is that Lookup allows you to have more than one value for a given key when Dictionary accepts only one.

So if in your case VersionNumber is unique then use Dictionary otherwise use Lookup.

You can simply transform your list into Dictionary or Lookup once:

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

So you do it once (perhaps when your app is loading) and then use it everywhere:

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

Again, if you need Lookup then replace ToDictionary with ToLookup ;)

于 2012-07-22T06:52:06.873 回答