Тип возвращаемого значения метода

в 11:12, , рубрики: .net, c#.net, метки:

Скажу сразу, возможно есть какое то более удачное решение проблемы описанной мною ниже — буду рад узнать!

Очень давно писал я настольное приложение на C#, в котором, сразу после запуска, пользователь должен был ввести свои логин и пароль. Ну кажись все просто, вариантов реализации входа в приложение сотни. Например, создать класс DatabaseManager, добавить в нем метод Login, который должен принимать логин и пароль, и даже возвращать объект, допустим User (к примеру, если логин или пароль введены неверно, то метод возвращает null).

class User
{
     //поля класса
}

class DatabaseManager
{
   public User Login(string login, string password)
   {
      User user = null;
      //код метода
      return user;
   }
}


И теперь можно просто написать:

var user = new DatabaseManager().Login("myLogin", "myPassword");

Примерно из такого куска кода все и началось. Допустим пользователь без подключения к сети решил войти в программу, тогда в методе Login выбросится исключение — значит нужно добавить блок try catch туда.

public User Login(string login, string password)
{
      try
      {
         User user = null;
         //код метода
         return user;
      }
      catch(Exception){ return null; }
}

После изменения кода метода Login, появилась еще одна проблема, заключается которая в том, что невозможно понять, какое именно сообщение отображать пользователю если метод возвращает null («Логин или пароль введены неверно» или же сообщение например об ошибке внутри метода). Конечно можно изменить класс User, добавив туда дополнительные поля типа IsLoginSuccessfully (успешность входа так сказать) и Message (сообщение, например об ошибке внутри метода). И в блоке try catch (а именно в catch) возвращать объект User, в котором будут инициализированы эти поля. Но что делать если в программе таких методов много? Добавлять эти два поля во все объекты? А как быть если метод возвращает System.Int32, ему то мы не можем добавить свои два поля. Выход очень прост — написание generic класса.

Создадим класс:

public class OperationResult<T>
    {
        public string Message { get; private set; }
        public bool IsSuccessfully { get; private set; }
        //Любой объект, в данном случае User
        public T Obj { get; private set; }

        public OperationResult(T obj, string message, bool successfully = false)
        {
            this.Obj= obj;
            this.Message = message;
            this.IsSuccessfully = successfully;
        }
    }

Перепишем наш Login метод:

public OperationResult<User> Login(string login, string password)
{
      try
      {
         User user = null;
         //код метода
         return new OperationResult(user, "Успешно выполнено!", true);
      }
      catch(Exception exc)
      { 
         return new OperationResult(null, exc.Message);
      }
}

Теперь, после вызова метода Login, для пользователя всегда можно предоставить полную информацию о том, что случилось не так во время входа, будь то некорректные логин/пароль, или же недоступность сервера.

var operationResult = new DatabaseManager().Login("myLogin", "myPassword");
if(!operationResult.IsSuccessfully )
   MessageBox.Show(operationResult.Message);
else
   if(operationResult.Obj == null)
      MessageBox.Show("Логин или пароль введены неверно!");
   else
      MessageBox.Show("Вход выполнен успешно!");

Соответственно класс OperationResult можно сделать возвращаемым типом для многих методов. Мне кажется это очень удобно + информативно для пользователя.

Так что вот такой вот костыль, если это можно так назвать я придумал когда то, и пользуюсь этим по сей день.

Автор: stalsoft

Источник

Поделиться

* - обязательные к заполнению поля