2009-07-10 9 views
17

nie wiem ile niezliczoną ilość razy miałem napisać kod do sprawdzania poprawności argumenty ciągów:C#: walidacja Argument: null/puste struny

public RoomName(string name) 
{ 
    if (string.IsNullOrEmpty(name)) 
    { 
     throw new ArgumentException("Cannot be empty", "name"); 
    } 
} 

Czy mimo tego uniknąć? Czy istnieje jakiś mechanizm atrybutów lub projekt po zawarciu umowy, aby tego uniknąć? Czy nie ma sposobu, aby powiedzieć:

public RoomName(NotNullOrEmptyString name) 
{ 

bez konieczności tworzenia tego typu?

+0

Możesz znaleźć ten link w [Sprawdzanie argumentu za pomocą atrybutu i metody przechwytywania] (http://www.codinginstinct.com/2008/05/argument- validation-using-attributes.html) użyteczne – Joe

Odpowiedz

7

Możesz to zrobić poprzez wstrzyknięcie kodu z atrybutami.

Inną opcją, która pozwala zaoszczędzić czas kodowania, ale nadal daje dużo kontroli, byłoby użycie czegoś takiego jak CuttingEdge.Conditions. To zapewnia płynny interfejs służący do sprawdzania argumentów, więc można napisać:

name.Requires().IsNotNull(); 
1

Choć pytanie zostało odebrane jakiś czas temu, myślałem o tym samym problemem ostatnio. Sformalizowane umowy kodowe (z automatyczną weryfikacją lub kontrolą) wydają się dobrym pomysłem, ale ogólnie ich zdolność weryfikacji jest dość ograniczona, a dla prostych sprawdzeń, takich jak sprawdzanie pustych lub pustych ciągów, wymagają one tyle samo kodu (lub więcej) niż staromodne kontrole.

Paradoksalnie, najlepszą odpowiedzią moim zdaniem za sznurek przypadku jest rzeczywiście jedną lub dwie klasy, które zawinąć ciąg znaków, który został sprawdzony, aby nie być null, pusta lub white-space, i przekazać tę instancję wokół:

public class NonEmptyString : IComparable<NonEmptyString>, ... 
{ 
    private readonly string _value; 

    public NonEmptyString(string value) 
    { 
     if (value == null) 
     { 
      throw new ArgumentNullException("value"); 
     } 
     if (value.Length == 0) 
     {     
      throw NewStringIsEmptyException("value"); 
     } 
     _value = value; 
    } 

    public string Value 
    { 
     get { return _value; } 
    } 

    ... 
} 

public class NonWhiteSpaceString : NonEmptyString 
{ 
    .... 
} 

Jasne, przechodząc wokół tych przypadkach nie uniemożliwi konieczności sprawdzenia, czy są one wartość null siebie, ale ma pewne duże zalety:

  • nie trzeba sprawdzić na pusty lub biało ciągi spacji w kółko, które mogą być podatne na błędy w sytuacjach, w których ciąg znaków jest dużo przekazywany.
  • Tak jak zrobiłem w mojej implementacji, sprawdzanie wartości NULL jest czymś innym niż sprawdzanie pustej wartości (lub wartości białej spacji), ponieważ chcesz rzucić określony ArgumentNullException w poprzednim przypadku, a także ArgumentException w drugim.
  • Wyraźnie sygnalizuje ograniczenie wartości ciągu, tak jak ma to robić każda klasa owijająca. W rzeczywistości, jeśli masz łańcuch, który ma jakiekolwiek ograniczenia i jest on przekazywany dużo, zawsze zalecam zawinięcie go w klasę, która hermetyzuje czek i utrzymuje resztę kodu z kłopotów. Dobrym tego przykładem są łańcuchy, które muszą spełniać pewien regularny wyraz. Jednak odejdę od pytania tutaj ...
+1

Myślę, że musisz dodać śledzenie nazwy parametru do swojego rozwiązania. Jest tak, ponieważ większość osób uznałaby to za mylące, gdybyś zadzwonił do 'frob (string foo, string bar)' z 'frob (null," value ")' i otrzymał komunikat o błędzie 'System.ArgumentNullException: Value nie może mieć wartości NULL. Nazwa parametru: wartość' zamiast 'System.ArgumentNullException: Wartość nie może być pusta. Nazwa parametru: foo' –