【问题标题】:Switch statement with multiply conditions [Solved]具有多个条件的 switch 语句 [已解决]
【发布时间】:2021-07-30 05:55:44
【问题描述】:

我有这样的代码:

switch (array[0], array[1], array[2])
{
    case (EntityRoute.North, EntityRoute.West, EntityRoute.South):
        prohibitedRoute = EntityRoute.East;
        return true;
    
    case (EntityRoute.South, EntityRoute.West, EntityRoute.North):
        prohibitedRoute = EntityRoute.East;
        return true;
    
    case (EntityRoute.North, EntityRoute.East, EntityRoute.South):
        prohibitedRoute = EntityRoute.West;
        return true;
    
    case (EntityRoute.South, EntityRoute.East, EntityRoute.North):
        prohibitedRoute = EntityRoute.West;
        return true;
    
    case (EntityRoute.South, EntityRoute.East, EntityRoute.North):
        prohibitedRoute = EntityRoute.West;
        return true;
}

我想制作一个条件顺序不严格的系统。有没有办法在不写额外案例的情况下做到这一点?请注意我使用的是 C# 8.0,因为我在 Unity3D 中工作。

【问题讨论】:

  • @SomeBody 请重新阅读我的问题,我已经使用了多个条件

标签: c# unity3d c#-8.0


【解决方案1】:

不需要switch 声明。试试这个:

EntityRoute[] all = new [] { EntityRoute.North, EntityRoute.East, EntityRoute.South, EntityRoute.West,  };
EntityRoute[] array = new [] { EntityRoute.East, EntityRoute.South, EntityRoute.North, };
EntityRoute prohibitedRoute = all.Except(array).First();
Console.WriteLine(prohibitedRoute.ToString());

这给了我:

West

你甚至可以像这样定义all

EntityRoute[] all = Enum.GetValues(typeof(EntityRoute)).Cast<EntityRoute>().ToArray();

【讨论】:

  • 当无法使用标志时,这是一个很好的选择。
  • @Cleptus - 标志本身通常不是一个好的选择。使用标志检查值通常会变得非常混乱。我认为最好使用离散值。
  • 谢谢你的建议)all - 在这种情况下不是,因为我还有一个选择EntityRoute.None。您的第一个建议对我来说更好,再次感谢)
  • @ArcueidD'athemon - 你可以做到all.Except(array.StartWith(EntityRoute.None)).First()
  • @Enigmativity - 我认为没有必要。另外,我不喜欢经常使用 Linq,因为在 Unity 中这会导致死机或性能下降。所以我通常会避免和collection做交易,但是这里没有collection是不可能创建项目逻辑的。
【解决方案2】:

不,没有与您想要的相似的东西(签入单个 switch 多个对象)。

最接近的是 c# 8.0 中引入的switch expression,但它不会同时检查多个变量。

检查CSharphie's answer 最终建议为什么,如果您将枚举标记为Flags,真的不需要switch 语句。

【讨论】:

  • CSharphie's answer 的制作没有考虑到无法使用 [Flags] 或标志会破坏其他逻辑。给出了最佳解决方案here
【解决方案3】:

如果您不想使用标志,您也可以在实际检查之前订购您的值:

// Copy array to keep original values. Only needed if you need to access the original order later
var orderedArray = array.Copy();
Array.Sort(orderedArray);

switch (orderedArray[0], orderedArray[1], orderedArray[2])
{
    // Write your cases according to the values of your enum here
}

我认为这个解决方案是您实际问题的答案。

在您的具体情况下,我更喜欢Enigmativity 的解决方案。

【讨论】:

  • 就我而言,我突然不能使用[Flags]
【解决方案4】:

您可以使用 Tuple Patterns,它是 C# 8.0 的一部分

如下图

EntityRoute? prohibitedRoute = (array[0], array[1], array[2]) switch
        {
            (EntityRoute.North, EntityRoute.West, EntityRoute.South) => EntityRoute.East,
            (EntityRoute.South, EntityRoute.West, EntityRoute.North) => EntityRoute.East,
            (EntityRoute.North, EntityRoute.East, EntityRoute.South) => EntityRoute.West,
            (EntityRoute.South, EntityRoute.East, EntityRoute.North) => EntityRoute.West,
            _ => null
        };

【讨论】:

  • 请不要发布“仅链接”的答案。始终将内容直接放在您的答案中,并且仅将链接作为您发布的材料的参考。
  • Tuple 没有解决我的问题,因为物品顺序仍然很严格。
  • @ArcueidD'athemon 哦,好吧。在这种情况下,Enigmativity 的解决方案应该可以完成工作。
【解决方案5】:

假设这是一个Enum 并标有Flags(技术上没有必要),您可以这样做:

[Flags]
public enum EntityRoute
{
   North = 1,
   East = 2,
   South = 4,
   West = 8
}

您必须确保值是唯一的,因此枚举值的顺序无关紧要,Noth | East | SouthEast | North | South 相同,因此只能出现一次。

switch (array[0] | array[1] | array[2])
{
    case EntityRoute.North | EntityRoute.West | EntityRoute.South:
        prohibitedRoute = EntityRoute.East;
        return true;
            
    ....
}

请记住,这只有在 Enum 设置了正确的值(即 2 的幂)时才能正常工作。

但是,您不需要数组来存储值:

something = EntityRoute.South | EntityRoute.East;
...
something |= EntityRoute.South

我建议您阅读有关 c# 中标志枚举的主题。 https://stackoverflow.com/a/8480/1789202

然后你最终会发现你甚至不需要这个开关盒,如果你总是有 3 个方向并且结果是缺少一个。

【讨论】:

  • 真的switch (array[0] | array[1] | array[2]) 会检查一个值,即按位运算的结果,但由于“真的不需要”最终建议,这个答案确实有一些价值。
  • 我知道[Flags],但我的情况无法解决,因为: 1. 我需要枚举值后面有严格的整数。 2. 我不需要像North | South | West | East 这样的值,因为这会破坏路线方向逻辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-20
  • 2016-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-28
相关资源
最近更新 更多