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(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#打开类型[重复]的主要内容,如果未能解决你的问题,请参考以下文章