C# EventArg类型的开关大小写

C# EventArg类型的开关大小写,c#,.net,switch-statement,C#,.net,Switch Statement,是否可以围绕EventArgs创建一个switch case语句 即: 现在我找不到一种方法将它放在开关盒中,所以我使用if-else语句,当我在其中填充许多if-else语句时,这将比开关盒慢,因为开关盒在引擎盖下面创建了某种类型的盒的哈希表。在开关盒块中,每个盒都必须静态计算。这意味着在每种情况下都需要一个常量。这篇文章可能也很有用只是为了完整性,这是可行的,但你不应该这样做,原因很明显: void MyMethod(object sender, EventArgs e) { swi

是否可以围绕EventArgs创建一个switch case语句

即:


现在我找不到一种方法将它放在开关盒中,所以我使用if-else语句,当我在其中填充许多if-else语句时,这将比开关盒慢,因为开关盒在引擎盖下面创建了某种类型的盒的哈希表。

在开关盒块中,每个盒都必须静态计算。这意味着在每种情况下都需要一个常量。这篇文章可能也很有用

只是为了完整性,这是可行的,但你不应该这样做,原因很明显:

void MyMethod(object sender, EventArgs e)
{
    switch(e.GetType().FullName)
    {
        case "MyNamespace.MyEventArgs":
            //seriously, don't do this.
            break;
        case "System.EventArgs":
            //this is the worst idea ever.
            break;
        default:
            break;
    }
}
您不能在场景中使用switch

switch语句需要一个整型或字符串作为参数,详情如下。不能将EventArgs作为参数传递给switch语句,case语句也需要编译时常量值

如果您查看以下内容:

开关语句的控制类型由开关建立 表情

如果开关表达式的类型是sbyte、byte、short、ushort、int、uint、long、ulong、bool、char、string或枚举类型,或者 是对应于这些类型之一的可空类型,则 是switch语句的控制类型。 否则,从开关表达式类型到以下类型之一,必须存在一个用户定义的隐式转换§6.4 可能的管理类型:sbyte、byte、short、ushort、int、uint、, long、ulong、char、string或,对应于1的可空类型 那些类型的。 否则,如果不存在此类隐式转换,或者如果存在多个此类隐式转换,则会出现编译时错误 发生。 代码中的另一个问题是case语句:

每个案例标签指定一个常量值

您的case语句指定了一个在编译时无法确定的值

这使您可以选择使用if-else块。除非您正在处理数百种类型的EventArg,否则您不太可能看到任何显著的性能提升

你可以用字典试试:


你想过使用方法重载吗? 一般来说,我会尽量避免使用switch-case块(视图异常除外),因为它们通常是一种气味,继承、重载等可以更好地解决问题


BR

您真的不会注意到速度上的任何差异。您的目标是仅在自定义EventArgs对象传递给您的方法时执行代码吗?我是说。。。在这种情况下,是否有任何非定制的EventArgs对象需要一些代码执行?首先处于这种困境通常表明您的设计可以更好地结构化。这是有意义的。我想我现在就把它留给if-else语句。我只处理4-5个不同的EventArgs atm,但以后可能会使用更多。我想如果我真的想把它放在一个开关的情况下,我可以包装自定义eventargs,并给它一个枚举值来代替case。但无论如何,if-else更适合使用。谢谢。@grmihel,而且,据我记忆所及,对于switch语句中小于5的情况,编译器不会创建查找表。您也可以考虑重新设计您的解决方案,因为这看起来像是一种代码味道。我不确定是否需要重新设计。方法是捕捉事件,然后确定发送哪个响应。当然,如果事件数量急剧增加,我必须将其分解为多个部分:我们的想法是一样的,但这将是一个非常丑陋的实现,但它肯定会工作,除非你突然弄乱了名称空间:以这种方式实现它会让你在听起来很有趣的地方获得提名。您能举个例子吗?对于要处理的每种类型的EventArgs,简单的方法重载:void MyMethodobject sender,MyEventArgs e{/*do some code*/}。。。。void MyMethodobject sender,MyOtherEventArgs e{/*执行一些其他代码*/},这样可以避免swith case块,因为类型由方法签名分隔。当然,您总是可以使事情过于复杂,所以您必须确定这样的sthg在您的具体代码中是否有意义。但是,我总是把开关盒当作嗅觉,粗略地看一下是否应该重构。
void MyMethod(object sender, EventArgs e)
{
    switch(e.GetType().FullName)
    {
        case "MyNamespace.MyEventArgs":
            //seriously, don't do this.
            break;
        case "System.EventArgs":
            //this is the worst idea ever.
            break;
        default:
            break;
    }
}
private static Dictionary<Type, Action<EventArgs>> _EventDispatcher;

static Program()
{
    _EventDispatcher = new Dictionary<Type, Action<EventArgs>>();
    _EventDispatcher.Add(typeof(EventArgs), OnEventArgs);
    _EventDispatcher.Add(typeof(MyEventArgs), OnMyEventArgs);
}

private static void MyMethod(object sender, EventArgs e)
{
    Action<EventArgs> eventMethod;

    if (!_EventDispatcher.TryGetValue(e.GetType(), out eventMethod))
        eventMethod = OnUnknownEventArgs;

    eventMethod(e);
}

private static void OnEventArgs(EventArgs e)
{
    Console.WriteLine("Simple event args: " + e);
}

private static void OnMyEventArgs(EventArgs e)
{
    var myEventArgs = (MyEventArgs)e;
    Console.WriteLine("My event args: " + myEventArgs);
}

private static void OnUnknownEventArgs(EventArgs e)
{
    Console.WriteLine(String.Format("Unknown event args ({0}): {1}", e.GetType(), e);
}

private static void Main(string[] args)
{
    MyMethod(null, new EventArgs());
    MyMethod(null, new MyEventArgs());
    MyMethod(null, new AnotherEventArgs());

    Console.ReadKey();
}