0

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

类定义

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?

有人可以向我解释这是如何工作的吗?这是什么法术?当然,我可以以相同的方式处理这两个实例,因为它们共享一个公共基类,但我只是将其中一个转换为基类,并且我正在根据条件进行属性分配。此外,这是否被认为是一种好的做法,还是有什么我看不到的重大缺点?

4

3 回答 3

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;
于 2013-07-28T21:35:55.207 回答
1

有人可以向我解释这是如何工作的吗?

当然 - 它只是一个使用条件运算符来选择要用于表达式其余部分的值的表达式。表达式的整体类型是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.";

更好的方法是声明或者声明abtype BaseClass,此时您不需要演员表。

于 2013-07-28T21:39:03.807 回答
1

您使用的条件运算符(?)类似于这个更 redable 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 控制条件表达式的类型。

  • 如果 x 具有 X 类型并且 y 具有 Y 类型,则
    • 如果存在从 X 到 Y 但不从 Y 到 X 的隐式转换(第 6.1 节),则 Y 是条件表达式的类型。
    • 如果存在从 Y 到 X 的隐式转换(第 6.1 节),而不是从 X 到 Y,则 X 是条件表达式的类型。
  • 否则,无法确定表达式类型,并出现编译时错误

ClassA因此,由于and之间没有隐式转换ClassB(它们具有相同的基类),因此您必须手动转换它。

于 2013-07-28T21:30:50.697 回答