---
# System prepended metadata

title: How to handle large numbers of branches
tags: [c#, programing skill]

---

以下範例圖片皆為實際應用且運行中的程式碼

## 巢狀if
![範例1-1](https://hackmd.io/_uploads/rkB9Ppdih.png)
![範例1-2](https://hackmd.io/_uploads/Hyz3wT_o2.png)
![範例1-3](https://hackmd.io/_uploads/S1gRP6Oi2.png)
![範例1-4](https://hackmd.io/_uploads/Byvkdpdon.png)
![範例1-5](https://hackmd.io/_uploads/SyU-OaOs2.png)

## 非0即1的分支使用if，或是iif 三元運算子

```csharp
if(isSuccess)
{
    
}
else
{
    
}

var message = isSuccess == true ? "1" : "0";
```

## 超過2個分支，請使用switch case 或 switch pattern matching；數量在3-5個之間或視複雜程度自行權衡

[switch pattern-matching in msdn](https://learn.microsoft.com/zh-tw/dotnet/csharp/fundamentals/functional/pattern-matching)
```csharp
switch(operationType)
{
    case "add":
        break;
    case "delete":
        break;
    case "update":
        break;
    default:
        break;
}


public State PerformOperation(string command) =>
   command switch
   {
       "SystemTest" => RunDiagnostics(),
       "Start" => StartSystem(),
       "Stop" => StopSystem(),
       "Reset" => ResetToReady(),
       _ => throw new ArgumentException("Invalid string value for command", nameof(command)),
   };
```


## 已經超過5個或7個以上的分支，請使用Dictionary<string ,Func`<Action>>`的方式，利用字典+迴圈來擇一執行或條件判斷執行

```csharp
class Program
{
    public static int Add(int x, int y) => x + y;
    public static int Subtract(int x, int y) => x - y;
    public static int Multiply(int x, int y) => x * y;
    public static int Divide(int x, int y) => x / y;

    static void Main(string[] args)
    {
        var operations = new Dictionary<string, Func<int, int, int>>
        {
            { "add", Add },
            { "subtract", Subtract },
            { "multiply", Multiply },
            { "divide", Divide }
        };

        Console.WriteLine("Enter an operation (add, subtract, multiply, divide): ");
        string operation = Console.ReadLine().ToLower();

        Console.WriteLine("Enter the first operand: ");
        int operand1 = Int32.Parse(Console.ReadLine());

        Console.WriteLine("Enter the second operand: ");
        int operand2 = Int32.Parse(Console.ReadLine());

        if (operations.ContainsKey(operation))
        {
            int result = operations[operation](operand1, operand2);
            Console.WriteLine($"Result: {result}");
        }
        else
        {
            Console.WriteLine("Operation not recognized.");
        }
    }
}
```

## 其他

![範例2](https://hackmd.io/_uploads/Skbvdaujh.jpg)

是否有其他方式能避免使用大量if，觀察邏輯與規律撰寫演算法解決，以上圖為例在了解檔名與位置之間的關聯後，使用迴圈讀取陣列產生檔名，以下為簡單的實作

```csharp
public static class GeneratExtensions
{
    public static string MapToImage(this IEnumerable<int> list)
    {
        int count = 0;
        var result = "";
        foreach(var item in list)
        {
            count++;
            if(item>0)
                result += count.ToString();
        }
        result = string.IsNullOrEmpty(result) ?  "def" : result;
        return $"b{result}_map";
        
    }
}

public class MultipleIfTests
{
    [Theory]
    [Trait("map","image")]
    [InlineData(new[]{ 0, 0, 0, 0},"bdef_map")]
    [InlineData(new[]{ 1, 0, 0, 0},"b1_map")]
    [InlineData(new[]{ 1, 1, 0, 0},"b12_map")]
    [InlineData(new[]{ 1, 1, 1, 0},"b123_map")]
    [InlineData(new[]{ 1, 1, 1, 1},"b1234_map")]
    [InlineData(new[]{ 0, 1, 0, 0},"b2_map")]
    [InlineData(new[]{ 0, 1, 1, 0},"b23_map")]
    [InlineData(new[]{ 0, 1, 1, 1},"b234_map")]
    [InlineData(new[]{ 0, 0, 1, 0},"b3_map")]
    [InlineData(new[]{ 0, 0, 1, 1},"b34_map")]
    [InlineData(new[]{ 0, 0, 0, 1},"b4_map")]
    public void test_map_to_image(int[] map ,string imageName)
    {
        // Given
        List<int> list = new List<int>();
        list.AddRange(map);
        
        // When
        var value = list.MapToImage();
        
        // Then
        Assert.Equal(imageName,value);
    }
}
```

使用linq

```csharp
public class MultipleIfTests
{
    [Theory]
    [Trait("map","image")]
    [InlineData(new[]{ 0, 0, 0, 0},"bdef_map")]
    [InlineData(new[]{ 1, 0, 0, 0},"b1_map")]
    [InlineData(new[]{ 1, 1, 0, 0},"b12_map")]
    [InlineData(new[]{ 1, 1, 1, 0},"b123_map")]
    [InlineData(new[]{ 1, 1, 1, 1},"b1234_map")]
    [InlineData(new[]{ 0, 1, 0, 0},"b2_map")]
    [InlineData(new[]{ 0, 1, 1, 0},"b23_map")]
    [InlineData(new[]{ 0, 1, 1, 1},"b234_map")]
    [InlineData(new[]{ 0, 0, 1, 0},"b3_map")]
    [InlineData(new[]{ 0, 0, 1, 1},"b34_map")]
    [InlineData(new[]{ 0, 0, 0, 1},"b4_map")]
    public void test_map_to_image(int[] map ,string imageName)
    {
        // Given
        List<int> list = new List<int>();
        list.AddRange(map);
        
        // When
        var result = list
            .Select((value,index) => value > 0 ? (index + 1).ToString() : "")
            .Aggregate("",(current , next) => current + next);
        
        var value = $"b{ string.IsNullOrEmpty(result) ? "def" : result}_map";
        // Then
        Assert.Equal(imageName,value);
    }
}
```

使用function方式串接

```csharp
public static class LinqExtensions
{
    public static Func<int, int, string> HasValuePosition 
        => (value, index) => value > 0 ? (index + 1).ToString() : "";
    
    public static string MapToImage(this IEnumerable<int> list)
        => list
        .Select((value, index) => HasValuePosition(value, index))
        .Aggregate((current, next) => current + next).ToImageName();

    public static string ToImageName(this string value) 
        => $"b{(string.IsNullOrEmpty(value) ? "def" : value)}_map";
}

public class MultipleIfTests
{
    [Theory]
    [Trait("map", "has_value_position")]
    [InlineData(0, 0, "")]
    [InlineData(1, 0, "1")]
    [InlineData(1, 1, "2")]
    public void test_has_value_position(int val,int index,string expected)
    {
        // Given
        // When
        var result = LinqExtensions.HasValuePosition(val, index);
        // Then
        Assert.Equal(expected, result);
    }

    [Theory]
    [Trait("map", "image_name")]
    [InlineData("", "bdef_map")]
    [InlineData("1", "b1_map")]
    public void test_to_image_name(string value, string expected)
    {
        // Given
        // When
        var result = value.ToImageName();
        // Then
        Assert.Equal(expected, result);
    }

    [Theory]
    [Trait("map", "image")]
    [InlineData(new[] { 0, 0, 0, 0 }, "bdef_map")]
    [InlineData(new[] { 1, 0, 0, 0 },"b1_map")]
    [InlineData(new[] { 1, 1, 0, 0 }, "b12_map")]
    [InlineData(new[] { 1, 1 ,1, 0 }, "b123_map")]
    [InlineData(new[] { 1, 1, 1, 1 }, "b1234_map")]
    [InlineData(new[] { 0 ,1, 0, 0 }, "b2_map")]
    [InlineData(new[] { 0, 1, 1, 0 }, "b23_map")]
    [InlineData(new[] { 0, 1, 1, 1 }, "b234_map")]
    [InlineData(new[] { 0, 0, 1, 0 }, "b3_map")]
    [InlineData(new[] { 0, 0, 1, 1 }, "b34_map")]
    [InlineData(new[] { 0, 0, 0, 1 }, "b4_map")]
    public void test_map_to_image(int[] map, string imageName)
    {
        // Given
        List<int> list = new List<int>();
        list.AddRange(map);
        // When
        var value = list.MapToImage();
        // Then
        Assert.Equal(imageName, value);
    }
}
```