实现我自己的开关类时出现问题

时间:2011-04-21 04:13:56

标签: c#

我正在尝试实现一个自定义开关案例,只是为了好玩..

方法是我创建了一个继承字典对象的类

public class MySwitch<T> : Dictionary<string, Func<T>> 
    {
        public T Execute(string key)
        {
            if (this.ContainsKey(key)) return this[key]();
            else return default(T);
        } 
    }

我在

下使用
 new MySwitch<int>
    {
    { "case 1",  ()=> MessageBox.Show("From1") },
    { "case 2..10",  ()=>MessageBox.Show("From 2 to 10") },               
    }.Execute("case 2..10");

但是如果我指定“case 2”,它会给出一个默认值,因为该键不在字典中。

使“案例2..10”的整个目的是,如果用户在案例2到案例10 之间输入任何内容,它将执行相同的值。

有人可以帮我解决这个问题吗?

由于

3 个答案:

答案 0 :(得分:1)

字符串“case 2..10”存储在字典对象中,唯一的方法包含键返回ture是否恰好提供了该字符串。意味着你必须将确切的字符串“case 2..10”传递给containskey才能返回true。

答案 1 :(得分:0)

我的忠告是查看规范模式。

您可以让每个功能都附加一个或多个规范,然后执行相关功能(或者根据需要执行功能)。

简而言之:

public interface ISpecification<T>
{
    bool IsSatisfiedBy(T item);
}

具体实施:

public class IntegerRangeSpecification : ISpecification<int>
{
    private readonly int min;
    private readonly int max;

    public IntegerRangeSpecification(int min, int max)
    {
        this.min = min;
        this.max = max;
    }
    public bool IsSatisfiedBy(int item)
    {
        return (item >= min) && (item <= max);
    }
}

当然你宁愿拥有RangeSpecification<T> : ISpecification<T>,但这需要更多努力/设计(例如where T : IComparable)。

无论如何,我希望能让你走上正轨。

答案 2 :(得分:0)

首先,您可能希望封装字典而不是扩展字典,因为我怀疑您需要交换机类中字典的所有方法。

其次,您需要分开解析案例字符串并将自己的键添加到字典中。使用字符串作为键的方法让我觉得不是最好的想法。通过使用字符串作为键,您需要键完全匹配。如果您使字典使用整数键,则更改了它的初始化方式。保持你的开关精神,你可以做这样的事情:

public class Switch<T>
{
    private Dictionary<int, Func<T>> _switch = new Dictionary<int, Func<T>>();
    private Func<T> _defaultFunc;

    public Switch(Func<T> defaultFunc)
    {
        _defaultFunc = defaultFunc;
    }


    public void AddCase(Func<T> func, params int[] cases)
    {
        foreach (int caseID in cases)
        {
            _switch[caseID] = func;
        }
    }

    public void AddCase( int beginRange, int endRange, Func<T> func)
    {
        for (int i = beginRange; i <= endRange; i++)
        {
            _switch[i] = func;
        }
    }

    public T Execute(int caseID)
    {
        Func<T> func;
        if(_switch.TryGetValue(caseID, out func)){
            return func();
        }else{
           return _defaultFunc();
        }
    }
}

可以这样使用:

Switch<int> mySwitch = new Switch<int>(() => {Console.WriteLine("Default"); return 0;});
mySwitch.AddCase(() => { Console.WriteLine("1"); return 1; }, 1);
mySwitch.AddCase(2, 10, () => { Console.WriteLine("2 through 10"); return 1; });

mySwitch.AddCase(() => { Console.WriteLine("11, 15, 17"); return 2; }, 11, 15, 17);

mySwitch.Execute(1);
mySwitch.Execute(2);
mySwitch.Execute(3);
mySwitch.Execute(4);
mySwitch.Execute(11);
mySwitch.Execute(12);
mySwitch.Execute(15);

有许多不同的方法可以达到你想要的效果。希望这有助于一些