英语轻松读发新版了,欢迎下载、更新

程序设计的问题 c#

sirtel 发布于 2017年02月16日
无人欣赏。

我打算写一个程序,调用dll,根据用户不同的设定,从服务器读取相应的数据。比如,用户需要设置为SettingOne的A型数据,则调用dll,设置一些参数,调用GetA()。

因为GetA()速度很慢,每次当用户想要A型数据时,需要很长的时间得到返回值,所以想“缓存”以前用过的数据。我在Obj class里,用了Dictionary<Setting, object> ObjValues记录之前获取过的数据。当setting一致时,如果字典里没有对应的值,则调用dll,若有,返回对应的值。

这里用Dictionary<Setting, object>不是最佳的做法吧?因为object还要被转换成string, int, double[]做余下的处理。

问题是,如何有效的“缓存”多种类型的数据,可以最快地查找到数据?

using System;
using System.Collections.Generic;

namespace test
{
    public static class DLL // cannot change the dll
    {
        public static int Setting1 { get; set; }
        public static int Setting2 { get; set; }
        public static string Setting3 { get; set; }
        public static string GetA() { /* Sleep(10 years) */ return ""; }
        public static int GetB() { /* Sleep(10 years) */ return 0; }
        public static double[] GetC() { /* Sleep(10 years) */ return new double[] { 0 }; }
    }

    public class Obj
    {
        public Dictionary<Setting, object> ObjValues = new Dictionary<Setting, object>();
        public void GetValue(Setting setting)
        {
            DLL.Setting1 = setting.Setting1; DLL.Setting2 = setting.Setting2; DLL.Setting3 = setting.Setting3;
            ObjValues[setting] = GetValue(setting.Type); // cache data
        }

        private object GetValue(ObjType type)
        {
            switch (type)
            {
                // loading data from database is assumed to be expensive.
                case ObjType.A: return DLL.GetA();
                case ObjType.B: return DLL.GetB();
                case ObjType.C: return DLL.GetC();
                default: return null;
            }
        }
    }

    public class Setting
    {
        public ObjType Type { get; set; }
        public int Setting1 { get; set; }
        public int Setting2 { get; set; }
        public string Setting3 { get; set; }
    }

    public enum ObjType { A, B, C, D, E }

    public class App
    {
        public static void Main(string[] args)
        {
            Obj obj = new Obj();
            List<Setting> settings = new List<Setting>() { /* SettingOne, SettingTwo, SettingThree ... */};
            foreach (Setting setting in settings)
            {
                if (obj.ObjValues.ContainsKey(setting))
                {
                    Console.WriteLine(obj.ObjValues[setting]); // use the cached data
                }
                else
                {
                    obj.GetValue(setting);
                    Console.WriteLine(obj.ObjValues[setting]);
                }
            }
        }
    }
}
共3条回复
tinyfool 回复于 2017年02月16日

Dictionary缓存成object还是什么,这跟性能关系不大。按照你的问题,只要你有缓存,性能就会比直接从网上拉快。

xiaotie 回复于 2017年02月16日

这个性能没啥好操心的,直接用 Object 转来转去的就行了。当然,考虑提高那么一丁点儿性能,以及加上类型约束以免运行时出错,代码可以这样写:

void Main()
{
Setting<Int32> setting1 = new Setting<int> { Key = "setting1" };
setting1.Set(10);
Console.WriteLine(setting1.Get());
MySetting setting2 = new MySetting { Key = "mysetting" };
setting2.Set("blablabla......");
Console.WriteLine(setting2.Get());
}

public class Setting<T>
{
protected static Dictionary<Setting<T>, T> _cache = new Dictionary<Setting<T>, T>();

public string Key { get; set; } = String.Empty;

public T Get()
{
    T val = default(T);
    lock(_cache) 
        _cache.TryGetValue(this, out val);
    return val;
}

public void Set(T val)
{
    lock (_cache)
        _cache[this] = val;
}

public override int GetHashCode()
{
    return this.Key.GetHashCode();
}
}

public class MySetting : Setting<String> { }
sirtel 回复于 2017年02月16日

2楼 @xiaotie 对对对,就是这样!应该用,避免出错

登录 或者 注册