C#中的案例/开关语句

时间:2015-11-18 14:37:37

标签: c# vb.net

我想知道是否有一种方法可以声明大量案例陈述而无需编写所有案例陈述。例如,我的代码:

            switch (Weight)
            {
                case 0 to 2;
                    ShippingCost = "3.69";

                case 3 to 4;
                    ShippingCost = "4.86";

                case 5 to 6;
                    ShippingCost = "5.63";

                case 7 to 8;
                    ShippingCost = "5.98";

                case 9 to 10;
                    ShippingCost = "6.28";

                case 11 to 30;
                    ShippingCost = "15.72";

            }

我开始将VB转换为C#,并意识到为了拥有多个case语句,你必须声明它们。你可以看到我有11到30而且不想拥有所有这些线条。

10 个答案:

答案 0 :(得分:13)

您无法在VB中使用C#中的比较。但可以使用直通案例,如下所示:

case 0:
case 1:
case 2:
  ShippingCost = "3.69";
  break;

case 3:
case 4:
  ShippingCost = "4.86";
  break;

请注意,非空案例需要throwreturnbreak语句。另请注意,您只能查看空案例。

编辑:

为了完整性,正如其他人所指出的那样,在这种情况下使用一系列if语句可能更为明智,如下所示:

if(Weight<=2) {
  ShippingCost = "3.69";
}
else if(Weight <= 4) {
  ShippingCost = "4.86";
}
... etc

答案 1 :(得分:6)

在C#中有直接的等价物,但是,你可以使用直通,所以你不必重复实现:

switch (Weight)
{
    case 0:
    case 1:
    case 2:
       ShippingCost = "3.69";
       break;
       ...

如果陈述在这种情况下可能更适合你:

if(Weight >= 0 && Weight <= 2){
    ShippingCost = "3.69";
} else if(Weight >= 3 && Weight <= 4){
    ShippingCost = "4.86";
}
...

答案 2 :(得分:5)

尝试这样:此解决方案无需在&&语句中编写else if

if(Weight >= 11 && Weight <= 30)
{
   ShippingCost = "15.72";
}
else if(Weight >= 9)
{
   ShippingCost = "6.28";
}
else if(Weight >= 7)
{
   ShippingCost = "5.98";
}
else if(Weight >= 5)
{
   ShippingCost = "5.63";
}
else if(Weight >= 3)
{
   ShippingCost = "4.86";
}
else if(Weight >= 0)
{
   ShippingCost = "3.69";
}

答案 3 :(得分:5)

你也可以把它写成Linq one liner:

var ShippingCost = (new[] { new { w = 2, p = "3,69" }, 
                            new { w = 4, p = "4.86" }, 
                            new { w = 6, p = "5.63" }, 
                            new { w = 8, p = "5.98" }, 
                            new { w = 10, p = "6.28" }, 
                            new { w = 30, p = "15.72" }})
             .First(x => Weight <= x.w).p;

正如其他人已经说过的那样,您希望确保重量超过30的物品的运输也能正确处理。

答案 4 :(得分:4)

如何使用这种方法

private static double GetShippingCost(double weight)
{
    if (weight > 30) throw new ArgumentException("Weight over allowed maximum", "weight");

    if (weight <= 2) return 3.69;
    if (weight <= 4) return 4.86;
    if (weight <= 6) return 5.63;
    if (weight <= 8) return 5.98;
    if (weight <= 10) return 6.28;
    if (weight <= 30) return 15.72;

}

答案 5 :(得分:3)

使用case的另一种方法是编写某种类来进行映射,例如:

public sealed class CostsPerWeight
{
    class CostPerWeight
    {
        public int Low;
        public int High;
        public double Cost;
    }

    readonly List<CostPerWeight> costs = new List<CostPerWeight>();

    public CostsPerWeight Add(int low, int high, double result)
    {
        // Error handling omitted for brevity. 
        // Real code should check that low < high and that ranges do not overlap.

        costs.Add(new CostPerWeight { Low = low, High = high, Cost = result } );
        return this;
    }

    public double Cost(int weight)
    {
        // This throws if the weight isn't in the list.
        // If that's not what you want, you'd have to add extra error handling here.
        return costs.First(x => x.Low <= weight && weight <= x.High).Cost;
    }
}

你会像这样使用(我使用双打而不是字符串来代替这个例子的成本,但你可以使用你需要的任何类型):

var costs = new CostsPerWeight()
    .Add( 0,  2,  3.69)
    .Add( 3,  4,  4.86)
    .Add( 5,  6,  5.63)
    .Add( 7,  8,  5.98)
    .Add( 9, 10,  6.28)
    .Add(11, 30, 15.72);

double shippingCost = costs.Cost(weight);

如果VB中有很多这些switch语句,那么值得考虑这种方法。

(使用它而不是Linq one-liner的优点就是它更容易记录和单元测试。你也可以创建一个CostsPerWeight类实例并传递它 - 对于解耦代码,依赖很有用 - 注射和单元测试。)

在我看来,基于权重查找成本的概念迫切需要封装在一个类中,而不是在代码的各个部分中逐个嵌入。

以下是CostsPerWeight的更多扩展示例,其中包含更多错误处理:

public class CostsPerWeight
{
    class CostPerWeight
    {
        public int Low;
        public int High;
        public double Cost;
    }

    readonly List<CostPerWeight> costs = new List<CostPerWeight>();

    double min = double.MaxValue;
    double max = double.MinValue;
    double costForMin;

    public CostsPerWeight Add(int low, int high, double cost)
    {
        if (low > high)
            throw new ArgumentException(nameof(low) + " must be less than " + nameof(high));

        if (cost < 0)
            throw new ArgumentOutOfRangeException(nameof(cost), "cost must be greater than zero");

        costs.Add(new CostPerWeight { Low = low, High = high, Cost = cost } );

        if (low < min)
        {
            min = low;
            costForMin = cost;
        }

        if (high > max)
            max = high;

        return this;
    }

    public double Cost(int weight)
    {
        if (weight < min)
            return costForMin;

        if (weight > max)
            throw new InvalidOperationException($"Weight {weight} is out of range: Must be <= {max}");

        return costs.First(x => x.Low <= weight && weight <= x.High).Cost;
    }
}

答案 6 :(得分:3)

最明确的方法是将数据放入对象中。

  private struct ShippingCost
  {
      public int MinWeight;
      public int MaxWeight;
      public decimal Cost;

      public ShippingCost(int min, int max, decimal cost)
      {
         MinWeight = min;
         MaxWeight = max;
         Cost = cost;
      }
  }

  private List<ShippingCost> Costs = new List<ShippingCost>
  {
      new ShippingCost(0, 2, 3.69m),
      new ShippingCost(3, 4, 4.86m),
      new ShippingCost(5, 6, 5.63m),
      new ShippingCost(7, 8, 5.98m),
      new ShippingCost(9, 10, 6.28m),
      new ShippingCost(11, 30, 15.72m),
  };

  // Choose shipping cost
  public decimal CalcShippingCost(int weight)
  {
      foreach (ShippingCost sc in Costs)
      {
          if (weight >= sc.MinWeight && weight <= sc.MaxWeight)
              return sc.Cost;
      }

      return 0.00m;     // default cost
  }

答案 7 :(得分:1)

你不能在C#中做到这一点。如果您的最大重量值是30,那么最好的选择是使用默认情况。

否则,如果你不想要像

这样的东西
case 11:
case 12:
case 13:
....
case 28:
case 29:
case 30:

“oldschool”if / else if将是最易读的解决方案

答案 8 :(得分:0)

我建议将数据存储在容器中并迭代容器。您可以创建自己的类或使用类似于Tuple的.net类:

var shippingCostsByWeight = new List<Tuple<int, int, string>>
{
    new Tuple<int, int, string>(0, 2, "3.69"),
    new Tuple<int, int, string>(3, 4, "4.86"),
    new Tuple<int, int, string>(5, 6, "5.63"),
    new Tuple<int, int, string>(7, 8, "5.98"),
    new Tuple<int, int, string>(9, 10, "6.28"),
    new Tuple<int, int, string>(11, 30, "15.72"),
};

ShippingCost = shippingCostsByWeight
                .First(tuple => weight >= tuple.Item1 && weight <= tuple.Item2).Item3;

答案 9 :(得分:-1)

您可以使用fall-through case switch语句,如下所示:

case 0:
case 1:
case 2:
  shippingCost = "3.69";
  break;

... and so on

这将导致0将shippingCost设置为3.69以及1和2. :) 这将是我对此的解决方案