有没有一种方法可以使用三元运算符-或类似的方法-来选择要分配给该变量的变量?

时间:2018-11-18 14:44:24

标签: c# .net ternary-operator

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

(bEquipAsSecondary ? currentWeaponOffhand : currentWeaponMainhand) = weaponToSwitchTo;

代替

if (bEquipAsSecondary)
{
    currentWeaponOffhand = weaponToSwitchTo;
}
else
{
    currentWeaponMainhand = weaponToSwitchTo;
}

这将导致以下错误

  

错误CS0131分配的左侧必须是变量,属性或索引器

所以我想知道是否有一种方法可以减少使用的空间,并且-我认为-使其看起来更整洁?

4 个答案:

答案 0 :(得分:7)

不确定这是否真的有效,但是如果您真的想坚持使用三元运算符,这是我的2美分...

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

答案 1 :(得分:3)

不确定三元运算符是否比此处的常规<BODY> <DIV ID="test"></DIV> <button id="create">create it!</button> </BODY> 语句更好。但是您可以使用Action,如下所示:

if-else

答案 2 :(得分:0)

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

_ = 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

说明

  • _ =是必需的,因为只有在我们分配某物时,三元运算符才可用。在这里,我们将_用作“ discard”变量;也就是说,我们不在乎返回的值;只是操作本身会发生。

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

    • 所有其他都是您期望的标准三元运算符。但是,如有任何疑问,请说。

想法

这并不理想,因为您必须分别指定每个作业;但确实为您提供了一种速记形式...

我怀疑这通常不会在代码审查中被接受,因为它比标准的if / else方法可读性差。


NB:在其他一些语言中,可以使用的一个技巧是使条件充当数组的索引(例如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;
        }
    }
}

即尽管有几行代码定义了辅助方法,但是您可以将其作为一个衬里在各处重复使用,并且即使不是那么聪明,它也更具可读性。

答案 3 :(得分:0)

您可以使用三元运算符选择一个操作,该操作将更新右侧的广告位。

//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);