切换案例类型为c#

Céd*_*vin 60 .net c# optimization switch-statement

可能重复:
C# - "开启类型"有比这更好的选择吗?

你好假设我在类类型上得到一个很大的if/else.有没有办法用开关盒做到这一点?

示例:

function test(object obj)
{
if(obj is WebControl)
{

}else if(obj is TextBox)
{

}
else if(obj is ComboBox)
{

}
Run Code Online (Sandbox Code Playgroud)

等......

我想创造类似的东西

switch(obj)
{
case is TextBox:
break;
case is ComboBox:
break;

}
Run Code Online (Sandbox Code Playgroud)

}

Ste*_*eve 72

没有.

http://blogs.msdn.com/b/peterhal/archive/2005/07/05/435760.aspx

我们收到很多关于C#语言添加的请求,今天我将讨论一个比较常见的 - 开启类型.打开类型看起来像一个非常有用和直接的功能:添加一个类似开关的结构,它打开表达式的类型,而不是值.这可能看起来像这样:

switch typeof(e) { 
        case int:    ... break; 
        case string: ... break; 
        case double: ... break; 
        default:     ... break; 
}
Run Code Online (Sandbox Code Playgroud)

这种语句对于在不相交的类型层次结构中添加虚拟方法(如调度)或在包含您不拥有的类型的类型层次结构上非常有用.看到这样的例子,您可以很容易地得出结论,该功能将是直截了当且有用的.它甚至可能让你想到"为什么那些#*&%$懒惰的C#语言设计师只是让我的生活更轻松,并添加这种简单,省时的语言功能?"

不幸的是,像许多"简单"的语言功能一样,类型切换并不像它第一次出现那么简单.当你看到一个更重要的,同样重要的例子时,麻烦就开始了:

class C {}
interface I {}
class D : C, I {}

switch typeof(e) {
case C: … break;
case I: … break;
default: … break;
}
Run Code Online (Sandbox Code Playgroud)

链接:https://blogs.msdn.microsoft.com/peterhal/2005/07/05/many-questions-switch-on-type/

  • 答案的其余部分在哪里?它现在结束于"...,这样的例子:" (37认同)
  • 对于登陆此页面的任何人的更新:自C#7以来答案是肯定的.您现在可以在类型上完全编写切换案例.请参阅:https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/ (6认同)
  • @oɔɯǝɹ如果您想阅读整篇文章,我提供了我的信息来源链接.当你可以在源头阅读时,我不打算粘贴整个报价.简单的答案是"不". (5认同)
  • 我不同意语言设计师.许多语言都有类型开关.无论如何,虽然没有类型开关,但很容易实现,请参阅http://stackoverflow.com/questions/7252186/switch-case-on-type-c/7301514#7301514 (4认同)
  • 我不在乎他说什么。很简单'。相反,如果他们从一开始就将 C# 设计得更好的话,情况就会更好。我听说所有语法都有 10 多个遍:(。Switch 本质上是 obj.member。vtable 是一个不可访问的成员。如果将其视为一个值(如 int),您可以使用它。 (2认同)

cdi*_*ins 54

以下代码或多或少地起作用,因为人们期望只查看实际类型的类型开关(例如,返回的内容GetType()).

public static void TestTypeSwitch()
{
    var ts = new TypeSwitch()
        .Case((int x) => Console.WriteLine("int"))
        .Case((bool x) => Console.WriteLine("bool"))
        .Case((string x) => Console.WriteLine("string"));

    ts.Switch(42);     
    ts.Switch(false);  
    ts.Switch("hello"); 
}
Run Code Online (Sandbox Code Playgroud)

这是使其工作所需的机器.

public class TypeSwitch
{
    Dictionary<Type, Action<object>> matches = new Dictionary<Type, Action<object>>();
    public TypeSwitch Case<T>(Action<T> action) { matches.Add(typeof(T), (x) => action((T)x)); return this; } 
    public void Switch(object x) { matches[x.GetType()](x); }
}
Run Code Online (Sandbox Code Playgroud)

  • 当"在某些方面这是可怕的"? (8认同)
  • 非常有趣的解决方案......在某些方面,这很糟糕:) ...但在某些方面,这是令人难以置信的(特别是在其他一些外部开发人员可以通过创建类“X”然后提供'如何处理 X' 逻辑...有点像迷你 DI/Ioc) (2认同)

Tim*_*uri 24

是的,你可以打开名字......

switch (obj.GetType().Name)
{
    case "TextBox":...
}
Run Code Online (Sandbox Code Playgroud)

  • 假设你知道所有可能的子类,当然. (8认同)
  • 我想编写这段代码的人是出于某种原因编写它...并且知道所有子类:P - 例如,他可能试图为所有"文本框"添加一个CssClass名称,然后添加所有"日期选择器"或其他任何内容. (3认同)
  • 我知道这是旧的,但我喜欢你的答案,我同意你的理由,写这个的人会知道他们所有的子类,只要他们使用switch语句来指定特定类的动作,而不是全部儿童班 (3认同)

Eni*_*ity 13

这是一个保持真实的选项我可以满足OP要求能够打开类型.如果你足够眯眼,它几乎看起来像一个真正的开关声明.

调用代码如下所示:

var @switch = this.Switch(new []
{
    this.Case<WebControl>(x => { /* WebControl code here */ }),
    this.Case<TextBox>(x => { /* TextBox code here */ }),
    this.Case<ComboBox>(x => { /* ComboBox code here */ }),
});

@switch(obj);
Run Code Online (Sandbox Code Playgroud)

x上述每个拉姆达是强类型.不需要铸造.

为了实现这项神奇的工作,您需要以下两种方法:

private Action<object> Switch(params Func<object, Action>[] tests)
{
    return o =>
    {
        var @case = tests
            .Select(f => f(o))
            .FirstOrDefault(a => a != null);

        if (@case != null)
        {
            @case();
        }
    };
}

private Func<object, Action> Case<T>(Action<T> action)
{
    return o => o is T ? (Action)(() => action((T)o)) : (Action)null;
}
Run Code Online (Sandbox Code Playgroud)

几乎给你的眼睛带来了眼泪,对吧?

尽管如此,它仍然有效.请享用.

  • "new [] {"和"}"是多余的. (2认同)

Fra*_*lli 9

最简单的事情可能是使用动力学,即你定义简单的方法,如Yuval Peled答案:

void Test(WebControl c)
{
...
}

void Test(ComboBox c)
{
...
}
Run Code Online (Sandbox Code Playgroud)

然后你不能直接调用Test(obj),因为重载解析是在编译时完成的.您必须将对象分配给动态,然后调用Test方法:

dynamic dynObj = obj;
Test(dynObj);
Run Code Online (Sandbox Code Playgroud)