C# 取决于条件的财产分配

C# 取决于条件的财产分配,c#,.net,design-patterns,compilation,C#,.net,Design Patterns,Compilation,最近,我在重写一些旧代码,特别是收缩太长的函数(减少开销,扩展可读性等等)。因此,我对一些实际有效的东西感到困惑: 类定义 执行 输出 有人能给我解释一下这是怎么回事吗?这是什么魔法?当然,我可以用相同的方式处理这两个实例,因为它们共享一个公共基类,但我只将其中一个强制转换为基类,并且根据一个条件进行属性赋值。此外,这被认为是一种良好的做法,还是有我看不到的明显缺点?如果,您使用的是与此更可编辑的类似的: if (a == null) b.BaseProperty = "..."; el

最近,我在重写一些旧代码,特别是收缩太长的函数(减少开销,扩展可读性等等)。因此,我对一些实际有效的东西感到困惑:

类定义 执行 输出 有人能给我解释一下这是怎么回事吗?这是什么魔法?当然,我可以用相同的方式处理这两个实例,因为它们共享一个公共基类,但我只将其中一个强制转换为基类,并且根据一个条件进行属性赋值。此外,这被认为是一种良好的做法,还是有我看不到的明显缺点?

如果,您使用的是与此更可编辑的
类似的

if (a == null)
    b.BaseProperty = "...";
else
    a.BaseProperty = "...";
Console.WriteLine(b.BaseProperty);
此代码中的强制转换

(a == null ? (BaseClass)b : a).BaseProperty = "..."
只是需要,因为条件运算符需要知道类型。条件表达式的类型必须与这两个表达式的类型一致

因此,在我看来,这是一种糟糕的做法,因为不清楚你在做什么


为什么需要转换为
基类
:C#5.0规范的相关部分是7.14,条件运算符:

?运算符的第二个和第三个操作数x和y控制条件表达式的类型

  • 如果x的类型是x,y的类型是y,那么
    • 如果存在从X到Y的隐式转换(§6.1),但不存在从Y到X的隐式转换,则Y是条件表达式的类型
    • 如果存在从Y到X的隐式转换(§6.1),但不存在从X到Y的隐式转换,则X是条件表达式的类型
  • 否则,将无法确定表达式类型,并发生编译时错误
因此,由于
ClassA
ClassB
之间没有隐式转换(它们只有相同的基类),因此必须强制转换

如果
,您使用的是与此更可编辑的
类似的版本:

if (a == null)
    b.BaseProperty = "...";
else
    a.BaseProperty = "...";
Console.WriteLine(b.BaseProperty);
 (a == null ? (BaseClass)b : a)
此代码中的强制转换

(a == null ? (BaseClass)b : a).BaseProperty = "..."
只是需要,因为条件运算符需要知道类型。条件表达式的类型必须与这两个表达式的类型一致

因此,在我看来,这是一种糟糕的做法,因为不清楚你在做什么


为什么需要转换为
基类
:C#5.0规范的相关部分是7.14,条件运算符:

?运算符的第二个和第三个操作数x和y控制条件表达式的类型

  • 如果x的类型是x,y的类型是y,那么
    • 如果存在从X到Y的隐式转换(§6.1),但不存在从Y到X的隐式转换,则Y是条件表达式的类型
    • 如果存在从Y到X的隐式转换(§6.1),但不存在从X到Y的隐式转换,则X是条件表达式的类型
  • 否则,将无法确定表达式类型,并发生编译时错误
因此,由于
ClassA
ClassB
之间没有隐式转换(它们只有相同的基类),因此必须强制转换

 (a == null ? (BaseClass)b : a)

有人能给我解释一下这是怎么回事吗

当然-它只是一个表达式,使用条件运算符选择表达式其余部分使用的值。表达式的总体类型为
BaseClass
,因为这是第二个操作数的确切类型,第三个操作数可以转换为它。您需要对其中一个操作数进行强制转换,因为表达式的总体类型必须是第二个操作数的类型或第三个操作数的类型。。。但是
ClassA
ClassB
都不合适

另外,这是一个好的做法还是有我看不到的明显的缺点

嗯,我觉得它很难看。我将使用空合并运算符,并将其提取到一个单独的局部变量中,以便于说明:

BaseClass target = a ?? (BaseClass) b;
target.BaseProperty = "Jon Skeet prefers this approach";
你仍然可以用一句话来表达,但我发现它的可读性较差:

(a ?? (BaseClass) b).BaseProperty = "Jon Skeet doesn't like 'clever' code.";
更好的做法是将
a
b
声明为
BaseClass
类型,此时您不需要强制转换

有人能给我解释一下这是怎么回事吗

当然-它只是一个表达式,使用条件运算符选择表达式其余部分使用的值。表达式的总体类型为
BaseClass
,因为这是第二个操作数的确切类型,第三个操作数可以转换为它。您需要对其中一个操作数进行强制转换,因为表达式的总体类型必须是第二个操作数的类型或第三个操作数的类型。。。但是
ClassA
ClassB
都不合适

另外,这是一个好的做法还是有我看不到的明显的缺点

嗯,我觉得它很难看。我将使用空合并运算符,并将其提取到一个单独的局部变量中,以便于说明:

BaseClass target = a ?? (BaseClass) b;
target.BaseProperty = "Jon Skeet prefers this approach";
你仍然可以用一句话来表达,但我发现它的可读性较差:

(a ?? (BaseClass) b).BaseProperty = "Jon Skeet doesn't like 'clever' code.";

更好的做法是将
a
b
声明为
BaseClass
类型,此时您不需要强制转换。

a确实等于null,因此它调用b.BaseProperty,看起来确实是一种非常不可靠的代码编写方法,尽管a确实等于null,所以它调用b.BaseProperty,虽然这不是因为B和a之间没有隐式转换:
((基类)(a==null?B:a))。PropertyBase=“hello”
查看
文档,我不记得它到底是怎么说的,但想法是整个运算符的返回类型是由第一个值参数定义的。在你的例子中,它是
(BaseClass)b
,这显然是
BaseClass
a
可以很容易地隐式转换到它。或者看看Tim Schmelter的评论,他解释得更好。实际上,Jon Skeet给了我一个很好的解释:
你需要在其中一个