如何實現隱式型別轉換

2023-01-05 12:01:21

Result 型別是許多程式語言中處理錯誤的常用方式,包括 C# 的 dotNext 庫。在本文中,我們將通過例子回顧 C# 中 using 語句和隱式型別轉換的使用。

預期效果

下面是一個範例程式碼,演示了 Result 型別的使用方法:

namespace TestProject1;

public class GetResultTests
{
    [Test]
    public void Test1()
    {
        // 通過 GetResult 方法獲取 Result 型別的返回值
        var result = GetResult();
        Assert.Pass();
    }

    public Result GetResult()
    {
        if (DateTime.Now.Second > 30)
        {
            // 如果成功,返回 Ok
            return Ok();
        }
        else
        {
            // 如果失敗,返回 Error
            return Error();
        }
    }
}

此文為了簡易演示沒有演示帶值的 Result 型別,實際使用中可以通過泛型來實現帶值的 Result 型別。

下面我們來通過一些步驟來實現這個功能。

static using 與 global using

在 C# 中,using 語句用於指定要包含在程式碼檔案中的名稱空間。其中特殊的,Static Using 和 Global Using 需要特別介紹一下。

Static Using 允許你在不指定名稱空間的情況下存取名稱空間中的型別。特別對於靜態方法,這很有用。

例如,你可以使用以下程式碼使用 Static Using:

using static System.Math;

double x = 3.14;
double y = Sqrt(x);
Console.WriteLine(y); // Outputs 1.77

在這個例子中,我們使用 Static Using 將 System.Math 名稱空間包含在程式碼檔案中,並使用 Sqrt 函數。

Global Using 允許你在整個程式碼檔案中包含名稱空間中的所有型別。

int[] numbers = { 1, 2, 3, 4, 5 };
int sum = numbers.Sum();
Console.WriteLine(sum); // Outputs 15

而在 Using.cs 檔案中,我們可以使用 Global Using:

global using System.Linq;

在這個例子中,我們使用 Global Using 將 System.Linq 名稱空間包含在程式碼檔案中,並使用 Sum 函數計算陣列 numbers 中的所有元素的和。

隱式型別轉換

隱式型別轉換允許你在不指定轉換的情況下將一種型別的值轉換為另一種型別。當你有一種型別的值,並需要將其作為另一種型別使用時,這很有用。

例如,你可以使用以下程式碼使用隱式型別轉換將一個整數轉換為一個 double:

int x = 1234;
double y = x;
Console.WriteLine(y); // Outputs 1234

我們也可以為自定義型別實現型別的隱式轉換。比如此處我們定義一個 Id 型別,並且讓其支援從 string 進行隱式型別轉換。

public struct Id
{
    public string Value { get; }

    public Id(string value)
    {
        Value = value;
    }

    public static implicit operator Id(string value) => new Id(value);
}

那麼我們就可以使用以下程式碼進行隱式型別轉換:

Id id = "123";

實現 Result 型別

我們可以通過上面的知識來實現 Result 型別。

首先,我們定義一個 Result 型別,它包含一個 IsSuccess 屬性。

public readonly struct Result
{
    public Result(bool isSuccess)
    {
        IsSuccess = isSuccess;
    }

    public bool IsSuccess { get; }
}

然後我們分別定義兩種型別的 Result,分別是 Ok 和 Error。

public readonly struct ErrorTag
{
}

public readonly struct SuccessTag
{
}

並且,我們在 Result 型別中實現對應的隱式型別轉換。

public readonly struct Result
{
    public Result(bool isSuccess)
    {
        IsSuccess = isSuccess;
    }

    public bool IsSuccess { get; }

    public static implicit operator Result(SuccessTag _) => new Result(true);
    public static implicit operator Result(ErrorTag _) => new Result(false);
}

這樣,我們就可以使用以下程式碼來建立 Result 型別的範例:

Result ok = new SuccessTag();
Result error = new ErrorTag();

然後我們在按照預期,使用方法來取代 new SuccessTag() 和 new ErrorTag()。

public static class ResultHelper
{
    public static SuccessTag Ok() => new();
    public static ErrorTag Error() => new();
}

這樣,我們就可以使用以下程式碼來建立 Result 型別的範例:

Result ok = ResultHelper.Ok();
Result error = ResultHelper.Error();

最終,我配合 static using 語法和 global using 語法。

global using static ResultHelper;

這樣,我們就可以使用以下程式碼來建立 Result 型別的範例:

Result ok = Ok();
Result error = Error();

總結

本文介紹了隱式型別轉換的概念,並且通過隱式型別轉換來實現 Result 型別。

參考資料

  • Global using Directive in C# 10[1]
  • Static using[2]
  • dotNext Result Type[3]
  • User-defined explicit and implicit conversion operators[4]
  • 本文作者: newbe36524
  • 本文連結: https://www.newbe.pro/ChatAI/0x012-How-to-implement-implicit-type-conversion/
  • 版權宣告: 本部落格所有文章除特別宣告外,均採用 BY-NC-SA 許可協定。轉載請註明出處!

參考資料

[1]

Global using Directive in C# 10: https://www.c-sharpcorner.com/article/global-using-directive-in-c-sharp-102/

[2]

Static using: https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/using-directive?WT.mc_id=DX-MVP-5003606#static-modifier

[3]

dotNext Result Type: https://dotnet.github.io/dotNext/features/core/result.html

[4]

User-defined explicit and implicit conversion operators: https://learn.microsoft.com/dotnet/csharp/language-reference/operators/user-defined-conversion-operators?WT.mc_id=DX-MVP-5003606