在实现我自己的开关类时遇到问题

本文关键字:遇到 问题 开关 实现 我自己 自己的 | 更新日期: 2023-09-27 17:52:42

我正在尝试实现一个自定义开关情况只是为了好玩。

方法是,我创建了一个继承字典对象的类
public class MySwitch<T> : Dictionary<string, Func<T>> 
    {
        public T Execute(string key)
        {
            if (this.ContainsKey(key)) return this[key]();
            else return default(T);
        } 
    }

我在

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

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

使"case 2.. "10 "表示如果用户输入的值在第2种情况到第10种情况之间,它将执行相同的值。谁能帮我解决这个问题?

谢谢

在实现我自己的开关类时遇到问题

字符串"case 2.. "10 ' '被存储在字典对象中,唯一包含键返回true的方法是你提供那个字符串。这意味着你必须传递确切的字符串"case 2.. "

我的建议是查看规范模式。

你可以让每个函数附加一个或多个规范,然后执行相关的函数(如果你愿意,可以执行多个函数)。

简而言之:

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)。

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

首先,您可能希望封装字典而不是扩展字典,因为我怀疑您希望在switch类中包含字典的所有方法。

其次,您需要解析大小写字符串,并将您自己的键添加到字典中。使用字符串作为键的方法给我的印象不是最好的想法。通过使用字符串作为键,您需要键完全匹配。如果你让你的字典使用整数键并且你改变了它的初始化方式。按照你的切换精神,你可以这样做:

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);

有很多不同的方法可以实现你想要的。希望对大家有所帮助