[英]Case/Switch Statements in C#
我想知道是否有一種方法可以聲明很多case語句而不必全部編寫。 例如,我的代碼:
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,並且不想擁有所有這些行。
您不能像在VB中那樣在C#中使用比較。 但是,您可以使用掉落情況,例如:
case 0:
case 1:
case 2:
ShippingCost = "3.69";
break;
case 3:
case 4:
ShippingCost = "4.86";
break;
請注意,非空情況需要throw
, return
或break
語句。 另請注意,您只能在空箱情況下失敗。
編輯:
為完整性起見,正如其他人指出的那樣,在這種情況下使用一系列if
語句可能更明智,例如:
if(Weight<=2) {
ShippingCost = "3.69";
}
else if(Weight <= 4) {
ShippingCost = "4.86";
}
... etc
在C#中有直接等效項,但是,您可以使用穿透(fall-through),因此不必重復執行:
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";
}
...
像這樣嘗試:此解決方案無需在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";
}
您也可以將其編寫為Linq one襯紙:
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的物品的運輸也得到正確處理。
如何使用這種方法
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;
}
使用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單行代碼的好處是,它更易於記錄和進行單元測試。您還可以創建CostsPerWeight
類實例並將其傳遞給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;
}
}
最清晰的方法是將數據放入對象中。
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
}
您無法在C#中做到這一點。 如果您的體重最大值是30,最好的選擇是使用默認情況。
否則,如果您不想要類似
case 11:
case 12:
case 13:
....
case 28:
case 29:
case 30:
“老式” if / else if將是最易讀的解決方案
我建議將數據存儲在容器中並遍歷該容器。 您可以創建自己的類或使用諸如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;
您可以使用以下情況切換語句:
case 0:
case 1:
case 2:
shippingCost = "3.69";
break;
... and so on
這將導致0將shippingCost設置為3.69以及1和2。:)
那就是我的解決方案
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.