C#打开类型[重复]

Posted

技术标签:

【中文标题】C#打开类型[重复]【英文标题】:C# switch on type [duplicate] 【发布时间】:2011-05-27 13:56:14 【问题描述】:

可能重复:C# - Is there a better alternative than this to 'switch on type'?

C# 不支持切换对象的类型。 模拟这个的最佳模式是什么:

switch (typeof(MyObj))
    case Type1:
    case Type2:
    case Type3:

【问题讨论】:

或动态调度:***.com/questions/3902496/… 你能描述一下为什么你要打开一个对象的类型吗?那会有所帮助。另外,类型之间的关系是什么?它们是否都有共同的基本类型(对象除外)?它们都是类类型吗?有没有一个对象可以属于您的类型类别的两个的情况? (例如,如果它们中的两个是接口并且对象实现了这两者。)这些类型是否曾经可以为空值类型?枚举?代表?泛型委托和接口的协方差曾经是一个因素吗? 另见***.com/questions/156467/switch-pattern-matching-idea ***.com/questions/7252186/switch-case-on-type-c-sharp ***.com/questions/7542793/… ***.com/questions/298976/… C# 7 现在提供了这个...模式匹配。很酷的示例参考:visualstudiomagazine.com/articles/2017/02/01/… C# 7 模式匹配文档 - docs.microsoft.com/en-us/dotnet/csharp/language-reference/… 【参考方案1】:

见gjvdkamp's answer;此功能现在存在于 C# 中


我通常使用类型和委托的字典。

var @switch = new Dictionary<Type, Action> 
     typeof(Type1), () => ... ,
     typeof(Type2), () => ... ,
     typeof(Type3), () => ... ,
;

@switch[typeof(MyType)]();

它有点不灵活,因为你不能通过案例,继续等等。但无论如何我很少这样做。

【讨论】:

您可能应该检查该类型是否在字典中。可以像这样相当简单if(@switch.ContainsKey(typeof(MyType))) @switch[typeof(MyType)](); 这应该是一个非常有效/高性能的解决方案。请注意,这不适用于子类。 @YevgeniGrinberg 我还没有测试过这个,但我确信 typeof(object) != typeof(MyType) 即使 MyType 是对象的子类。 如果您想要一个适用于子类型的解决方案,那么在某些时候必须使用IsAssignableFrom 进行比较。 This answer supports sub-types 但它的用法有点冗长 我宁愿使用Action action; if(@switch.TryGetValue(typeof(Type1), out action) action(); 而不是搜索两次..(包含和索引器)【参考方案2】:

更新: 这在 C# 7.0 中通过pattern matching 得到了修复

switch (MyObj)
    case Type1 t1: 
    case Type2 t2:
    case Type3 t3:

旧答案:

这是 C# 游戏中的一个漏洞,还没有灵丹妙药。

您应该在“访问者模式”上进行谷歌搜索,但这对您来说可能有点繁重,但您仍然应该了解一些内容。

这是使用 Linq 对此事的另一种看法:http://community.bartdesmet.net/blogs/bart/archive/2008/03/30/a-functional-c-type-switch.aspx

否则这些方面的东西可能会有所帮助

// nasty..
switch(MyObj.GetType().ToString())
  case "Type1": etc


// clumsy...
if myObj  is Type1 then
if myObj is Type2 then

等等

【讨论】:

功能 c 型开关的问题在于它没有获得实际 switch-case 语法所获得的预编译速度。这可能会诱骗程序员过度使用这个 look-alike 类,以为它具有相同的优势。这看起来像是更昂贵的if-then-with-lambdas 的迷人包装。 抱歉,ToString 似乎是一个糟糕的计划 - 因为使用 Visual Studio 重命名类型会破坏这一点。为什么不typeOf(Type1) 这没有回答问题。问题是关于打开类型,而不是关于打开对象的类型。 该代码示例从字面上切换了 MyObj 的类型。 您能否更新此内容以显示如何打开实际的 Type 实例?有类似switch (typeInstance) case int: ... 【参考方案3】:

a simple answer to this question 使用类型字典查找 lambda 函数。以下是它的使用方法:

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

在模式匹配方面还有a generalized solution to this problem(类型和运行时检查条件):

var getRentPrice = new PatternMatcher<int>()
    .Case<MotorCycle>(bike => 100 + bike.Cylinders * 10) 
    .Case<Bicycle>(30) 
    .Case<Car>(car => car.EngineType == EngineType.Diesel, car => 220 + car.Doors * 20)
    .Case<Car>(car => car.EngineType == EngineType.Gasoline, car => 200 + car.Doors * 20)
    .Default(0);

var vehicles = new object[] 
    new Car  EngineType = EngineType.Diesel, Doors = 2 ,
    new Car  EngineType = EngineType.Diesel, Doors = 4 ,
    new Car  EngineType = EngineType.Gasoline, Doors = 3 ,
    new Car  EngineType = EngineType.Gasoline, Doors = 5 ,
    new Bicycle(),
    new MotorCycle  Cylinders = 2 ,
    new MotorCycle  Cylinders = 3 ,
;

foreach (var v in vehicles)

    Console.WriteLine("Vehicle of type 0 costs 1 to rent", v.GetType(), getRentPrice.Match(v));

【讨论】:

【参考方案4】:

我曾经做过一次解决方法,希望对您有所帮助。

string fullName = typeof(MyObj).FullName;

switch (fullName)

    case "fullName1":
    case "fullName2":
    case "fullName3":

【讨论】:

如果您重命名/移动任何类,这种方法很脆弱。 稍微重构一下,你就完蛋了。 这在 C# 6.0 中使用 nameof 时不那么脆弱:case nameof() 您将使用 nameof() 而不是 nameof()。例如,在上面的示例中,nameof(MyObj)。但是我错了,因为这是打开全名,而 nameof 只会给你类名。 为什么不使用 case case nameof(MyClass): break; 以便它更可重构【参考方案5】:

我很少使用这种形式的switch-case。即使这样,我也找到了另一种方法来做我想做的事。如果您发现这是完成您需要的唯一方法,我会推荐@Mark H 的解决方案。

如果这是一种工厂创建决策过程,有更好的方法来做。否则,我真的不明白为什么要在类型上使用开关。

这是一个扩展 Mark 解决方案的小示例。我认为这是处理类型的好方法:

Dictionary<Type, Action> typeTests;

public ClassCtor()

    typeTests = new Dictionary<Type, Action> ();

    typeTests[typeof(int)] = () => DoIntegerStuff();
    typeTests[typeof(string)] = () => DoStringStuff();
    typeTests[typeof(bool)] = () => DoBooleanStuff();


private void DoBooleanStuff()

   //do stuff


private void DoStringStuff()

    //do stuff


private void DoIntegerStuff()

    //do stuff


public Action CheckTypeAction(Type TypeToTest)

    if (typeTests.Keys.Contains(TypeToTest))
        return typeTests[TypeToTest];

    return null; // or some other Action delegate

【讨论】:

以上是关于C#打开类型[重复]的主要内容,如果未能解决你的问题,请参考以下文章

使用 C# 打开 excel 实例 [重复]

如何打开一个exe。使用c#的文件[重复]

通过正则表达式在c#中打开html标签[重复]

Visual Studio c# winform打开链接[重复]

C#全局键盘钩子,从控制台应用程序打开一个表单[重复]

C# 语言:泛型、打开/关闭、绑定/未绑定、构造