有没有办法使用三元运算符 - 或类似的方法 - 来选择要分配的变量?

Posted

技术标签:

【中文标题】有没有办法使用三元运算符 - 或类似的方法 - 来选择要分配的变量?【英文标题】:Is there a way to use a ternary operator - or similar method - for picking the variable to assign to? 【发布时间】:2019-04-21 01:44:12 【问题描述】:

是否可以根据条件改变我分配给的变量?我遇到的问题是想要这样做:

(bEquipAsSecondary ? currentWeaponOffhand : currentWeaponMainhand) = weaponToSwitchTo;

代替

if (bEquipAsSecondary)

    currentWeaponOffhand = weaponToSwitchTo;

else

    currentWeaponMainhand = weaponToSwitchTo;

这会导致以下错误

错误 CS0131 赋值的左侧必须是变量、属性或索引器

所以我想知道是否有办法做到这一点来减少使用的空间 - 在我看来 - 让它看起来更整洁一点?

【问题讨论】:

currentWeaponOffhandcurrentWeaponMainhand 的具体类型是什么? 这些是类 【参考方案1】:

要使用三元运算符来选择要为其赋值的变量,您可以使用ref locals/returns。例如,

(bEquipAsSecondary ? ref currentWeaponOffhand : ref currentWeaponMainhand) = weaponToSwitchTo;

示例输出和代码

var currentWeaponOffhand = 4;
var currentWeaponMainhand = 5;
var weaponToSwitchTo = 7;

(bEquipAsSecondary ? ref currentWeaponOffhand : ref currentWeaponMainhand) = weaponToSwitchTo;
Console.WriteLine($"When bEquipAsSecondary=bEquipAsSecondary,currentWeaponOffhand=currentWeaponOffhand,currentWeaponMainhand=currentWeaponMainhand");

输出

When bEquipAsSecondary=False,currentWeaponOffhand=4,currentWeaponMainhand=7
When bEquipAsSecondary=True,currentWeaponOffhand=7,currentWeaponMainhand=5

【讨论】:

显然,您不需要var _ = 不错的一个!虽然需要等待统一包含 C#7.2 才能使用 byref locals/returns【参考方案2】:

不确定三元运算符是否比此处的常规 if-else 语句更好。但是你可以使用Action,像这样:

(bEquipAsSecondary ? new Action(() => currentWeaponOffhand = weaponToSwitchTo)
                   : () => currentWeaponMainhand = weaponToSwitchTo)();

【讨论】:

我喜欢这个解决方案,因为它可以概括为一个框架来处理所有游戏动作的效果:你为每个可能的状态突变创建一个Action,然后游戏逻辑会计算出哪个@987654326 @ 从它的集合中需要被执行,并执行它。【参考方案3】:

我能想到的最好的/最接近你的结果是:

_ = condition ? (a = c) : (b = c);

在上下文中:

bool condition = true;
int a = 1;
int b = 2;
int c = 3;

_ = condition ? (a = c) : (b = c);
Console.WriteLine($"a = a; b = b; c = c");

输出

a = 3; b = 2; c = 3

说明

_ = 是必需的,因为三元运算符仅在我们分配给某些东西时才可用。这里我们使用_作为“丢弃”变量;即我们不关心返回值;只是操作本身发生。

使用括号(例如(a = c) 需要在赋值周围,因为我们需要返回结果。执行a = c 会将c 的值分配给a,但不会向调用者返回任何内容。另一方面,(a = c)c 分配给a,然后输出a 的新值,使其在方法的其余部分的上下文中可用。即,该语句有效地从分配中读取@987654334 @。

其他一切都与您对标准三元运算符的期望相同。但是,有任何问题,请说。

想法

这并不理想,因为您必须单独指定每个分配;但确实给了你一种速记形式......

我怀疑这在代码审查中通常会被拒绝,因为它的可读性不如标准 if/else 方法...


注意:在其他一些语言中,可以使用的技巧是让条件充当数组的索引(例如 false=0,true=1),然后在分配值时利用它...但是,虽然您可以在 C# 中强制执行此操作,但它并不漂亮:

void Main()

    bool condition = true;  
    var a = new ReferenceType<int>(1);
    var b = new ReferenceType<int>(2);
    var c = new ReferenceType<int>(3);

    (new []b, a)[ConvertBoolToInt(condition)].Value = c.Value;
    Console.WriteLine($"a = a; b = b; c = c");    

//in C# bools aren't natively convertable to int as they are in many langauges, so we'd need to provide a conversion method
public int ConvertBoolToInt(bool value)

    return value ? 1 : 0;

//to allow us to change the value rather than only the refenence, we'd need to wrap our data in something and update the value assigned to its property
public class ReferenceType<T>

    public T Value get;set;
    public ReferenceType(T intValue)
    
        Value = intValue;
    
    public override string ToString()
    
        return Value.ToString();
    

也就是说,上面讨论的是创建一种更通用的方法...如果您的用例仅限于武器分配/类似用例,您可以使用类似的技巧,例如:

public enum WeaponHandEnum

    Primary //int = 0
    ,
    Secondary //int = 1

public class Player

    public Weapon[] Weapons get;set;
    public Player(Weapon primary = null, Weapon secondary = null)
    
        Weapons = new Weapon[2] primary, secondary; 
    
    public void Equip(WeaponHandEnum whichHand, Weapon newWeapon)
    
        Weapons[(int)whichHand] = newWeapon;
    

public class Weapon /* ... */ 

如果您发现必须在整个代码中执行大量这样的语句,并且想要一种方法来减少行数,那么您最好使用以下方法:

void Main()

    bool condition = true;  
    var a = 1;
    var b = 2;
    var c = 3;
    SomeKindaHelper.TernaryAssign<int>(condition, ref a, ref b, c);
    Console.WriteLine($"a = a; b = b; c = c");    

public static class SomeKindaHelper

    public static void TernaryAssign<T>(bool condition, ref T assignToMeIfConditionIsTrue, ref T assignToMeIfConditionIsFalse, T newValue)
    
        if (condition)
        
            assignToMeIfConditionIsTrue = newValue;
        
        else 
        
            assignToMeIfConditionIsFalse = newValue;
        
    

即虽然这是定义辅助方法的几行代码,但您可以在整个地方重用它作为一个衬里,而且它更具可读性,如果不是那么聪明的话。

【讨论】:

感谢您的详尽回答! 别担心/祝你好运。显然,Anu 的解决方案更适合纯三元方法(我尝试过但处于 PS 模式,所以使用 [ref] 而不是 ref 并得出结论它不起作用;doh!)。祝你好运。【参考方案4】:

您可以使用三元运算符来选择一个动作来更新正确的槽。

//Define action to equip appropriate slot
var equipAction = bEquipAsSecondary
    ? new Action<Weapon>( w => currentWeaponOffhand = w )
    : new Action<Weapon>( w => currentWeaponMainhand = w );

//Now equip the weapon
equipAction(weaponToSwitchTo);

【讨论】:

以上是关于有没有办法使用三元运算符 - 或类似的方法 - 来选择要分配的变量?的主要内容,如果未能解决你的问题,请参考以下文章

python中的三元表达式(三目运算符)

无赋值的 Java 三元

三元条件下的多个 OR 运算符,

三元(三目)运算符

我可以使用 pine 脚本的三元运算符来指定 plotshape() 中的 style 参数或 plotchar() 中的 char 参数吗?

matlab中的三元运算符