看作C#无法打开一个Type(我收集的并不是作为特殊情况添加的,因为is-a关系意味着可能有多个不同的情况可能适用),是否有更好的方法来模拟切换类型?
void Foo(object o)
{
if (o is A)
{
((A)o).Hop();
}
else if (o is B)
{
((B)o).Skip();
}
else
{
throw new ArgumentException("Unexpected type: " + o.GetType());
}
}
Run Code Online (Sandbox Code Playgroud) 我最近一直在关注F#,虽然我不太可能在不久的将来跳过障碍,但它肯定会突出一些C#(或库支持)可以让生活更轻松的领域.
特别是,我正在考虑F#的模式匹配功能,它允许非常丰富的语法 - 比当前的开关/条件C#等价物更具表现力.我不会试图给出一个直接的例子(我的F#不符合它),但简而言之它允许:
虽然C#最终可以借用[ahem]丰富的一些内容,但是在过渡时期我一直在研究可以在运行时做些什么 - 例如,将一些对象拼凑起来相当容易:
var getRentPrice = new Switch<Vehicle, int>()
.Case<Motorcycle>(bike => 100 + bike.Cylinders * 10) // "bike" here is typed as Motorcycle
.Case<Bicycle>(30) // returns a constant
.Case<Car>(car => car.EngineType == EngineType.Diesel, car => 220 + car.Doors * 20)
.Case<Car>(car => car.EngineType == EngineType.Gasoline, car => 200 + car.Doors * 20)
.ElseThrow(); // or could use a Default(...) terminator
Run Code Online (Sandbox Code Playgroud)
其中getRentPrice是Func <Vehicle,int>.
[注意 - 也许这里的Switch/Case是错误的术语......但它显示了这个想法]
对我来说,这比使用重复的if/else或者复合三元条件(对于非平凡的表达式变得非常混乱 - 括号丰富)的等价物要清楚得多.它还避免了大量的转换,并允许简单扩展(直接或通过扩展方法)到更具体的匹配,例如InRange(...)匹配可比VB选择...案例"x到y "用法.
我只是想测量一下,如果人们认为上述结构有很多好处(在没有语言支持的情况下)?
另外请注意,我一直在玩上述3种变体: …
在编写switch语句时,在case语句中可以打开的内容似乎存在两个限制.
例如(是的,我知道,如果你正在做这种事情,这可能意味着你的面向对象(OO)架构是不确定的 - 这只是一个人为的例子!),
Type t = typeof(int);
switch (t) {
case typeof(int):
Console.WriteLine("int!");
break;
case typeof(string):
Console.WriteLine("string!");
break;
default:
Console.WriteLine("unknown!");
break;
}
Run Code Online (Sandbox Code Playgroud)
这里switch()语句失败,带有'一个预期的整数类型的值',case语句失败并带有'a expected value is expected'.
为什么会有这些限制,以及基本理由是什么?我看不出有任何理由switch语句具有只能屈从于静态分析,为什么在接通的值必须是完整的(即原语).理由是什么?
假设我可以选择在字符串比较的基础上识别代码路径,或者如果确定类型:
哪个更快,为什么?
switch(childNode.Name)
{
case "Bob":
break;
case "Jill":
break;
case "Marko":
break;
}
if(childNode is Bob)
{
}
elseif(childNode is Jill)
{
}
else if(childNode is Marko)
{
}
Run Code Online (Sandbox Code Playgroud)
更新:我问这个问题的主要原因是因为switch语句对于什么算是一个特例.例如,它不允许您使用变量,只允许移动到主程序集的常量.我认为它有这个限制,因为它正在做一些时髦的东西.如果它只是翻译成elseifs(作为一张海报评论)那么为什么我们不允许在case语句中使用变量?
警告:我是后期优化的.这种方法被称为许多在应用程序的缓慢一部分倍.
可能重复:
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)
}
我有一个对象:
ExampleClass ex = new ExampleClass();
Run Code Online (Sandbox Code Playgroud)
和:
Type TargetType
Run Code Online (Sandbox Code Playgroud)
我想将ex类型转换为TargetType所描述的类型:
Object o = (TargetType) ex;
Run Code Online (Sandbox Code Playgroud)
但当我这样做时,我得到:
找不到类型或命名空间名称't'
那怎么做?我在这里遗漏了一些东西吗?
更新:
我想得到这样的东西:
public CustomClass MyClassOuter
{
get
{
return (CustomClass) otherClass;
}
}
private otherClass;
Run Code Online (Sandbox Code Playgroud)
因为我会有很多这样的属性,我想这样做:
public CustomClass MyClassOuter
{
get
{
return (GetThisPropertyType()) otherClass;
}
}
private SomeOtherTypeClass otherClass;
Run Code Online (Sandbox Code Playgroud)
语境:
通常在我班级的上下文中,我需要创建许多属性.并且在每一个都取代铸造属性的类型.它对我来说似乎没有意义(在我的上下文中),因为我知道返回类型是什么,我想写一些代码来为我做演员.也许是仿制药的情况,我还不知道.
这就像我可以保证在这个属性中我得到正确的对象并且是正确的类型并且100%能够将它转换为属性类型.
所有我需要这样做,以便我不需要在每个属性中指定它必须"将值转换为CustomClass",我想做一些类似"将值转换为与此属性相同的类"的内容.
例如:
class MYBaseClass
{
protected List<Object> MyInternalObjects;
}
class MyClass
{
public SpecialClass MyVeryOwnSpecialObject
{
get
{
return (SpecialClass) MyInteralObjects["MyVeryOwnSpecialObject"];
}
}
}
Run Code Online (Sandbox Code Playgroud)
好吧 - 我可以制作上面这样的许多属性 - 但是有两个问题: …
可能重复:
"开启类型"有比这更好的选择吗?
我需要迭代我的类的所有属性,并检查我的类型int是否需要做什么,如果它的字符串..然后做一些事情.我需要使用开关盒.这里我以下面的方式使用switch,但它要求一些常量.看下面的代码:
public static bool ValidateProperties(object o)
{
if(o !=null)
{
var sourceType = o.GetType();
var properties = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Static);
foreach (var property in properties)
{
var type = property.GetType();
switch (type)
{
*case typeof(int):* getting error here
// d
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
另外我想知道,我应该使用什么检查,typeof(int)或typeof(Int32)?
class CustomClass<T> where T: bool
{
public CustomClass(T defaultValue)
{
init(defaultValue); // why can't the compiler just use void init(bool) here?
}
public void init(bool defaultValue)
{
}
// public void init(int defaultValue) will be implemented later
}
Run Code Online (Sandbox Code Playgroud)
你好.这似乎是一个简单的问题,但我在互联网上找不到答案:为什么编译器不会使用init方法?我只想为不同类型提供不同的方法.
而是打印以下错误消息:"'CustomClass.init(bool)'的最佳重载方法匹配'有一些无效的参数"
我很乐意提示.
最好的问候,克里斯
新的C#6.0nameof在使用PropertyChanged以下内容传播属性更改的模式中非常出色:
private string _myProperty;
public string MyProperty
{
get
{
return _myProperty;
}
set
{
_myProperty= value;
OnPropertyChanged(nameof(MyProperty));
}
}
Run Code Online (Sandbox Code Playgroud)
在监听属性更改时,我使用它(是的,即使是丑陋的硬编码字符串):
private void OnMyObjectPropertyChanged(object sender, PropertyChangedEventArgs args)
{
switch (args.PropertyName)
{
case "MyProperty":
DoSomething();
break;
}
}
Run Code Online (Sandbox Code Playgroud)
使用新的nameof表达式,这段代码会编译/工作吗?
private void OnMyObjectPropertyChanged(object sender, PropertyChangedEventArgs args)
{
switch (args.PropertyName)
{
case nameof(MyObject.MyProperty):
DoSomething();
break;
}
}
Run Code Online (Sandbox Code Playgroud) 可能重复:
C# - "开启类型"有比这更好的选择吗?
考虑经典:
class Widget { }
class RedWidget : Widget { }
class BlueWidget : Widget { }
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,在我的用户界面中,我可以对待所有Widget相同的内容.但是,我需要if或switch通过一些细微差别.
可能的方法:
枚举指标 - 由构造函数设置
enum WidgetVariety { Red, Blue }
class Widget {
public WidgetVariety Variety { get; protected set; }
}
class RedWidget : Widget {
public RedWidget() {
Variety = Red;
}
}
// Likewise for BlueWidget...
switch (mywidget.Variety) {
case WidgetVariety.Red:
// Red specific GUI stuff
case WidgetVariety.Blue:
// …Run Code Online (Sandbox Code Playgroud) c# ×10
.net ×2
.net-3.5 ×1
casting ×1
generics ×1
nameof ×1
optimization ×1
performance ×1
polymorphism ×1
roslyn ×1
system.type ×1
types ×1