简体   繁体   English

与条件有关的财产分配

[英]Condition-depending property assignment

Recently, I was rewriting some old code, especially shrink too long functions (reduce overhead, extend readability etc..). 最近,我正在重写一些旧代码,尤其是缩小太长的功能(减少开销,扩展可读性等)。 Thereby I stumpled about something that actually works: 因此,我为实际起作用的东西而苦恼:

Class definition 类定义

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; }
}

Execution 执行

ClassA a = null;
ClassB b = new ClassB();

(a == null ? (BaseClass)b : a).BaseProperty = "What would Jon Skeet think about this?";
Console.WriteLine(b.BaseProperty);

Output 输出量

What would Jon Skeet think about this?

Can someone explain to me how this works? 有人可以向我解释这是如何工作的吗? What is this sorcery? 这是什么法术? Of course I can handle both instances the same way as they share a common base class, but I'm only casting one of them to the base class and I'm doing a property assignment based on a condition. 当然,我可以用它们共享一个公共基类的方式来处理这两个实例,但是我只将其中一个强制转换为基类,并且根据条件进行属性分配。 Also, is this considered as a good practice or are there any significant downsides I just can't see? 另外,这被认为是一种好的做法吗?或者我是否看不到任何重大的缺点?

You are using the conditional operator(?) similiar to this more redable if : 您正在使用条件运算符(?)类同这更redable if

if (a == null)
    b.BaseProperty = "...";
else
    a.BaseProperty = "...";
Console.WriteLine(b.BaseProperty);

The cast in this code 此代码中的演员表

(a == null ? (BaseClass)b : a).BaseProperty = "..."

is just needed because the conditional operator needs to know the type. 仅需要此操作是因为条件运算符需要知道类型。 The type of the conditional expression must be consistent for both. 这两个条件表达式的类型必须一致。

So in my opinion it's bad practise since it's not clear what you're doing. 因此,我认为这是不好的做法,因为不清楚您在做什么。


Why the cast to BaseClass is required: the relevant section of the C# 5.0 spec is 7.14, the conditional operator: 为什么需要BaseClassBaseClass :C#5.0规范的相关部分为7.14,条件运算符为:

The second and third operands, x and y, of the ?: operator control the type of the conditional expression. ?:运算符的第二和第三操作数x和y控制条件表达式的类型。

  • If x has type X and y has type Y then 如果x具有X类型,而y具有Y类型,则
    • If an implicit conversion (§6.1) exists from X to Y, but not from Y to X, then Y is the type of the conditional expression. 如果存在从X到Y的隐式转换(第6.1节),但从Y到X不存在,则Y是条件表达式的类型。
    • If an implicit conversion (§6.1) exists from Y to X, but not from X to Y, then X is the type of the conditional expression. 如果存在从Y到X的隐式转换(第6.1节),但是从X到Y不存在,则X是条件表达式的类型。
  • Otherwise, no expression type can be determined, and a compile-time error occurs . 否则,将无法确定表达式类型,并且会发生编译时错误

So since there is no implicit conversion between ClassA and ClassB (they have just the same base class), you have to cast it mnaually. 因此,由于在ClassAClassB之间没有隐式转换(它们具有相同的基类),因此您必须手动转换它。

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

is

 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;

Can someone explain to me how this works? 有人可以向我解释这是如何工作的吗?

Sure - it's just an expression using the conditional operator to pick which value to use for the rest of the expression. 当然-这只是一个使用条件运算符的表达式,用于选择在表达式的其余部分中使用哪个值。 The overall type of the expression is BaseClass because that's the exact type of the second operand, and the third operand can be converted to it. 表达式的整体类型为BaseClass因为这是第二个操作数的确切类型,第三个操作数可以转换为该类型。 You need the cast on one of the operands, because the overall type of the expression has to be either the type of the second operand or the type of the third operand... but neither ClassA nor ClassB are suitable. 您需要对其中一个操作数进行强制转换,因为表达式的整体类型必须第二个操作数的类型第三个操作数的类型……但是ClassAClassB都不适合。

Also, is this considered as a good practice or are there any significant downsides I just can't see? 另外,这被认为是一种好的做法吗?或者我是否看不到任何重大的缺点?

Well it looks pretty ugly to me. 好吧,对我来说看起来很丑。 I'd use the null-coalescing operator instead, and extract it into a separate local variable for clarity: 我将改用null-coalescing运算符,并将其提取到一个单独的局部变量中以清楚显示:

BaseClass target = a ?? (BaseClass) b;
target.BaseProperty = "Jon Skeet prefers this approach";

You could still do it in one statement, but I find that less readable: 你仍然可以做到这一点在一个声明中,但我发现,不易阅读:

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

Even better would be to declare either a or b as being of type BaseClass , at which point you don't need the cast. 更好的方法是将ab声明为BaseClass类型,此时您不需要强制转换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM