最近,我正在重写一些旧代码,特别是缩减太长的函数(减少开销,扩展可读性等等)。因此,我弄清楚实际上有用的东西:
public abstract class BaseClass {
public string BaseProperty { get; set; }
}
public sealed class ClassA : BaseClass {
public string PropertyA { get; set; }
}
public sealed class ClassB : BaseClass {
public string PropertyB { get; set; }
}
ClassA a = null;
ClassB b = new ClassB();
(a == null ? (BaseClass)b : a).BaseProperty = "What would Jon Skeet think about this?";
Console.WriteLine(b.BaseProperty);
What would Jon Skeet think about this?
有人可以向我解释一下这是如何运作的吗?这巫术是什么?当然,我可以像共享一个公共基类一样处理这两个实例,但是我只将其中一个投射到基类中,并且我正在根据条件进行属性赋值。此外,这被认为是一种好的做法,还是有任何重大的缺点,我看不到?
答案 0 :(得分:1)
您正在使用conditional operator(?)类似于此更加可更新的if
:
if (a == null)
b.BaseProperty = "...";
else
a.BaseProperty = "...";
Console.WriteLine(b.BaseProperty);
此代码中的演员
(a == null ? (BaseClass)b : a).BaseProperty = "..."
只需要因为条件运算符需要知道类型。条件表达式的类型必须对两者都一致。
所以在我看来这是不好的做法,因为你不清楚你在做什么。
为什么需要转换为BaseClass
:C#5.0规范的相关部分是7.14,条件运算符:
?:运算符的第二个和第三个操作数x和y控制条件表达式的类型。
因为ClassA
和ClassB
之间没有隐式转换(它们只有相同的基类),所以你必须将其转换为mnaually。
答案 1 :(得分:1)
(a == null ? (BaseClass)b : a)
是
BaseClass x = null;
if(a == null)
x = (BaseClass)b;
else
x = (BaseClass)a; // Here is implicit cast to the type of the second argument of ? operator
return x;
答案 2 :(得分:1)
有人可以向我解释这是如何运作的吗?
当然 - 它只是一个表达式,使用条件运算符来选择用于表达式的 rest 的值。表达式的整体类型为BaseClass
,因为这是第二个操作数的确切类型,第三个操作数可以转换为它。您需要对操作数的一个进行强制转换,因为表达式的整体类型必须 第二个操作数的类型或第三个操作数的类型......但ClassA
和ClassB
都不合适。
此外,这被视为一种良好的做法,还是有任何重大的缺点,我看不到?
对我来说这看起来很难看。我会使用null-coalescing运算符,为了清楚起见将其提取到一个单独的局部变量中:
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
类型,此时您不需要演员。