Какой самый гладкий и привлекательный синтаксис вы нашли для подтверждения правильности параметров в c #? - PullRequest
29 голосов
/ 21 марта 2009

Обычная проблема любого языка - утверждать, что параметры, отправленные в метод, соответствуют вашим требованиям, а если нет, отправлять красивые, информативные сообщения об ошибках. Этот вид кода повторяется снова и снова, и мы часто пытаемся создать помощников для него. Однако в C # кажется, что эти помощники вынуждены иметь дело с некоторым дублированием, навязанным нам языком и компилятором. Чтобы показать, что я имею в виду, позвольте мне представить некоторый сырой код без помощников, а затем один возможный помощник. Затем я укажу на дублирование в помощнике и точно сформулирую мой вопрос.

Сначала код без всяких помощников:

public void SomeMethod(string firstName, string lastName, int age)
{
     if(firstName == null)
     {
          throw new WhateverException("The value for firstName cannot be null.");
     }

     if(lastName == null)
     {
          throw new WhateverException("The value for lastName cannot be null.");
     }

     // Same kind of code for age, making sure it is a reasonable range (< 150, for example).
     // You get the idea
}

}

Теперь код с разумной попыткой помощника:

public void SomeMethod(string firstName, string lastName, int age)
{
      Helper.Validate( x=> x !=null, "firstName", firstName);
      Helper.Validate( x=> x!= null, "lastName", lastName);
}

Основной вопрос заключается в следующем: Обратите внимание, как код должен передавать значение параметра и имя параметра ("firstName" и имя). Это сообщение об ошибке может сказать: «Бла-бла-бла, значение параметра firstName ». Вы нашли способ обойти это, используя отражение или что-то еще? Или способ сделать его менее болезненным?

И вообще, нашли ли вы другие способы упростить эту задачу проверки параметров при одновременном уменьшении дублирования кода?

РЕДАКТИРОВАТЬ: Я читал людей, говорящих об использовании свойства Parameters, но так и не нашел способ обойти это дублирование. Кому-нибудь повезет с этим?

Спасибо!

Ответы [ 14 ]

0 голосов
/ 23 марта 2009

Он не применяется везде, но может помочь во многих случаях:

Я полагаю, что SomeMethod выполняет некоторую поведенческую операцию с данными "фамилия", "имя" и "возраст" Оцените свой текущий дизайн кода. Если три части данных требуют класса, поместите их в класс. В этом классе вы также можете положить свои чеки. Это освободит "SomeMethod" от проверки ввода.

Конечный результат будет примерно таким:

public void SomeMethod(Person person)
{
    person.CheckInvariants();
    // code here ...
}

Вызов будет примерно таким (если вы используете .NET 3.5):

SomeMethod(new Person { FirstName = "Joe", LastName = "White", Age = 12 });

в предположении, что класс будет выглядеть так:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }

    public void CheckInvariants()
    {
        assertNotNull(FirstName, "first name");
        assertNotNull(LastName, "last name");
    }

    // here are your checks ...
    private void assertNotNull(string input, string hint)
    {
        if (input == null)
        {
            string message = string.Format("The given {0} is null.", hint);
            throw new ApplicationException(message);
        }
    }

Вместо синтаксического сахара в .NET 3.5 вы также можете использовать аргументы конструктора для создания объекта Person.

0 голосов
/ 21 марта 2009

Postsharp или другие AOP framework .

0 голосов
/ 21 марта 2009

Не знаю, переходит ли этот метод с C / C ++ на C #, но я сделал это с помощью макросов:


    #define CHECK_NULL(x)  { (x) != NULL || \
           fprintf(stderr, "The value of %s in %s, line %d is null.\n", \
           #x, __FILENAME__, __LINE__); }
 
0 голосов
/ 21 марта 2009

В этом случае вместо использования собственного типа исключения или действительно общих типов, таких как ApplicationException. Я думаю, что лучше использовать встроенные типы исключений, которые специально предназначены для этого использования:

Среди них .. System.ArgumentException, System.ArgumentNullException ...

...