2008-11-14 61 views
77

是否有一個簡單的屬性或數據約定可以分配給函數參數,以防止在C#/ .NET中傳遞null?理想情況下,這也將在編譯時檢查,以確保文字null沒有在任何地方使用,並在運行時拋出ArgumentNullException將參數標記爲不能在C#/ .NET中爲空?

目前,我喜歡寫東西......

if (null == arg) 
    throw new ArgumentNullException("arg"); 

...爲了我希望不會null每個參數。

在相同的音符,是有一個相對Nullable<>因此下面將失敗:

NonNullable<string> s = null; // throw some kind of exception 

回答

61

沒什麼可在編譯時,很遺憾。

我有一點hacky solution,我最近發佈在我的博客上,它使用了一個新的結構和轉換。

在.NET 4.0與Code Contracts的東西,生活會好很多。實際的語言語法和對非空性的支持仍然非常好,但代碼合同會有很大的幫助。

我也有一個名爲ThrowIfNull的MiscUtil的擴展方法,這使得它更簡單一些。

最後一點 - 使用「if (null == arg)」而不是「if (arg == null)」的任何原因?我發現後者更易於閱讀,前者在C中解決的問題不適用於C#。

+1

>不幸的是,編譯時沒有任何東西可用。 > ... >我非常高興擁有真正的語言語法和支持非空性 我同意。我也想看到編譯時錯誤被提出。 – AndrewJacksonZA 2009-10-02 12:25:45

+2

@Jon,如果碰巧有一個隱式轉換爲bool定義,「if(arg = null)」是否工作?我承認這看起來很不正當,但它確實編譯了...... – 2011-11-29 06:48:27

+10

@ ThomasS.Trias:是的,在這個令人難以置信的晦澀的邊緣案例中,*與存在拼寫錯誤並且缺少圍繞該代碼的測試相結合,最終會出現問題。到那時我認爲你有更大的問題,但:) – 2011-11-29 06:49:43

8

查看企業庫中的驗證器。當你想驗證它

private MyType _someVariable = TenantType.None; 
[NotNullValidator(MessageTemplate = "Some Variable can not be empty")] 
public MyType SomeVariable { 
    get { 
     return _someVariable; 
    } 
    set { 
     _someVariable = value; 
    } 
} 

然後在你的代碼:你可以不喜歡

Microsoft.Practices.EnterpriseLibrary.Validation.Validator myValidator = ValidationFactory.CreateValidator<MyClass>(); 

ValidationResults vrInfo = InternalValidator.Validate(myObject); 
-7
public void foo(int? id, string name) 
{ 
    if (id == null) 
    { 
     throw new ArgumentNullException("id"); 
    } 
    if (name == null) 
    { 
     throw new ArgumentNullException("name"); 
    } 

    this.foo = id.Value; 
    this.fooName = name; 
} 

你去那裏,否則只是定義其他聲明。

0

不是最漂亮的,但是:

public static bool ContainsNullParameters(object[] methodParams) 
{ 
    return (from o in methodParams where o == null).Count() > 0; 
} 

,你可以得到在ContainsNullParameters方法也更有創意:

public static bool ContainsNullParameters(Dictionary<string, object> methodParams, out ArgumentNullException containsNullParameters) 
     { 
      var nullParams = from o in methodParams 
          where o.Value == null 
          select o; 

      bool paramsNull = nullParams.Count() > 0; 


      if (paramsNull) 
      { 
       StringBuilder sb = new StringBuilder(); 
       foreach (var param in nullParams) 
        sb.Append(param.Key + " is null. "); 

       containsNullParameters = new ArgumentNullException(sb.ToString()); 
      } 
      else 
       containsNullParameters = null; 

      return paramsNull; 
     } 
當然

你可以使用攔截器或反射,但這些很容易遵循/使用很少的開銷

-2

好吧,這個回覆有點晚,但這裏是我如何解決它:

public static string Default(this string x) 
{ 
    return x ?? ""; 
} 

使用這個exension方法,那麼你可以把null和空字符串視爲同一件事。

E.g.

if (model.Day.Default() == "") 
{ 
    //.. Do something to handle no Day .. 
} 

不理想我知道,因爲你必須記得調用默認設置,但它是一個解決方案。

12

我知道這是一個很古老的問題,但是這一次是在這裏失蹤:

如果您使用ReSharper的你可以使用Annotated Framework

2

我知道我對這個問題感到難以置信的遲到,但我覺得答案會變得相關,因爲最新的C#主要版本接近發佈,然後發佈。在C#8.0中將發生重大變化,C#將假設所有類型被視爲非空。

根據的Mads託格森:

的問題是,空引用是如此有用。在C#中,它們是每個引用類型的默認值 。缺省值 值是什麼?變量有什麼其他價值,直到您可以決定 還有什麼其他值分配給它?還有什麼其他的價值可以爲我們分配一個新的 分配的參考數組,直到你到達 填充它?

此外,有時null本身是一個合理的價值。有時你想要表示一個字段沒有 值的事實 。通過「無」參數是可以的。雖然有時候重點是 。這裏還存在另一個問題: 像C#這樣的語言不會讓你表達這裏的空值是否是一個好主意。

因此,通過的Mads列出的分辨率是:

  1. 我們認爲,更普遍的是想引用不爲空。可空引用類型 將是最罕見的類型(儘管我們沒有很好的數據通過 告訴我們多少),所以它們是那些需要新註釋的類型。

  2. 該語言已經具有 - 可以爲空值的類型的語法的概念。這兩者之間的類比將使語言更容易在語言上增加語言 ,並且在語言上更簡單。

  3. 這似乎是正確的,你不應該給自己或消費者帶來麻煩的空值,除非你主動決定你想要它們。空,而不是缺少它們,應該是你明確必須選擇的東西。

所需特徵的示例:

public class Person 
{ 
    public string Name { get; set; } // Not Null 
    public string? Address { get; set; } // May be Null 
} 

預覽可用於Visual Studio 2017,15.5.4+預覽。

相關問題