簡體   English   中英

C#中可為空的字符串

[英]nullable string in C#

我知道只需使用null,C#中的字符串就可以為“ nullable”。

但是,可空類型的全部要點是我從編譯器獲得幫助[編輯:aka,類型錯誤:無法將蘋果添加到香蕉中]

而使用這種“類型系統”的“空性取決於底層類型”會破壞我可能擁有的任何保證(這並非易事,因為這似乎首先就是使用類型系統的全部要點。 )

如果願意,用C#處理此問題的標准方法是什么? 我是否要開設自己的“可空”課程?

編輯

我再改一下這個問題:

在C#中,確保被注釋為可為空的變量不會分配給未注釋為可為空的變量的標准方法是什么?

那就是: 所有類型的標准方式是什么,究竟是什么 關鍵字為您提供值類型。

如果您要詢問確保某個方法的返回類型不為null方法,則有一個解決方案:該方法必須返回值類型。 每個返回引用類型的方法都可能返回null 您無能為力。

因此,您可以創建一個這樣的struct以能夠返回值類型:

public struct SurelyNotNull<T>
{
    private readonly T _value;

    public SurelyNotNull(T value)
    {
        if(value == null)
            throw new ArgumentNullException("value");
        _value = value;
    }

    public T Value
    {
        get { return _value; }
    }
}

現在應該返回字符串的方法可以返回SurelyNotNull<string>

這種方法的問題是:
沒用 雖然保證方法的返回值不為null ,但SurelyNotNull<T>.Value的返回值不為。 乍一看,似乎可以保證它不為null。 但是可以這樣,因為:
每個結構都有一個隱式的,公共的,無參數的構造函數, 即使定義了另一個構造函數也是如此
以下代碼有效,並使用上面的struct編譯:

new SurelyNotNull<string>();

結論:
在C#中,您無法實現您想做的事情。
您仍然可以使用這種方法,您只需要了解有人可以使用此類型並且仍然產生空值。 要在這種情況下快速失敗,最好將檢查添加到Value的getter並在_value為null時引發異常。

正如丹尼爾·希爾加斯(Daniel Hilgarth)所指出的,沒有實現這一目標的防彈方法。 我的提議與他的提議相似,但又增加了一些安全性。 您可以自己決定收益是否超過在整個程序中使用包裝器類型的成本。

struct NonNull<T> where T : class {
    private readonly T _value;
    private readonly bool _isSafe;

    public NonNull(T value) {
        if (value == null)
            throw new ArgumentNullException();
        _value = value;
        _isSafe = true;
    }
    public T Value {
        get {
            if (_isSafe) return _value;
            throw new ArgumentNullException();
        }
    }
    public static implicit operator T(NonNull<T> nonNull) {
        return nonNull.Value;
    }
}

static class NonNull {
    public static NonNull<T> Create<T>(T value) where T : class {
        return new NonNull<T>(value);
    }
}

包裝器類型主要是為了使您的意圖能夠自我記錄,因此不太可能使用零初始化的結構來繞過它,但是它會保留一個標志以指示它是否已正確初始化。 在那種公認的異常情況下,訪問該值時將拋出ArgumentNullException

class Program {
    static void Main(string[] args) {
        IsEmptyString(NonNull.Create("abc")); //false
        IsEmptyString(NonNull.Create("")); //true
        IsEmptyString(null); //won't compile
        IsEmptyString(NonNull.Create<string>(null)); //ArgumentNullException 
        IsEmptyString(new NonNull<string>()); //bypassing, still ArgumentNullException
    }

    static bool IsEmptyString(NonNull<string> s) {
        return StringComparer.Ordinal.Equals(s, "");
    }
}

現在,這比偶爾的NRE好嗎? 也許。 它可以節省大量樣板參數檢查。 您需要確定是否適合您的情況。 缺少像F#這樣的編譯器支持,無法提供編譯時的空安全性,但是(可以說)您可以減輕運行時的安全性。

您可能希望在Microsoft的客戶反饋網站上投票解決此問題: 在C#中添加不可為空的引用類型

您需要類似NotNull屬性的東西。 使用這些將為您提供編譯時警告和錯誤,並且在某些情況下,IDE會反饋有關將NULL值分配給NotNull屬性的信息。

看到這個問題: C#:如何實現和使用NotNull和CanBeNull屬性

所有引用類型都可以為空。 字符串是引用類型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM