#c# #winforms #exception
#c# #winforms #исключение
Вопрос:
Привет, я разрабатываю приложение winform с использованием C # и entity framework (linq для entities). Предположим, что следующий escenario:
В методе некоторого класса я устанавливаю и объект значений со значениями формы
private void agrega_cliente_Click(object sender, EventArgs e)
{
cliente = new _Cliente();
try
{
cliente.nombres = nom_cliente.Text;
cliente.apellidoP = apellidoP_cliente.Text;
cliente.apellidoM = apellidoM_cliente.Text;
cliente.fechaNacimiento = fechaNacimientoPicker.Value.Date;
if (operaciones.AgregaCliente(cliente, referencias))
{
MessageBox.Show("Cliente Agregado");
this.Close();
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
Обратите внимание, что назначение и вызов метода «AgregaCliente» находятся между попыткой и перехватом, поэтому, если возникает исключение, окно сообщения покажет его.
Затем в другом классе у меня есть метод AgregaCliente, который вставляет значения в базу данных.
public bool AgregaCliente(_Cliente cliente, ArrayList refes)
{
try
{
Cliente cli = new Cliente()
{
Nombres = cliente.nombres,
ApellidoP = cliente.apellidoP,
ApellidoM = cliente.apellidoM,
FechaNac = cliente.fechaNacimiento
};
if (NombreExiste(cli))
context.clientes.AddObject(cli);
else
throw new System.ArgumentException("El usuario ya existe");
if (refes.Count != 0)
{
foreach (_Referencia elem in refes)
context.referencias_personales.AddObject(AgregaReferencia(elem));
}
context.SaveChanges();
}
catch (Exception ex)
{
return false;
}
return true;
}
Внутри этого метода есть вызов "NombreExiste()"
, который проверяет, что пользователь еще не вставлен, если пользователь существует, генерируется исключение.
Итак, проблема здесь в том, что если в "AgregaCliente"
методе генерируется исключение, я хочу, чтобы это исключение было перехвачено "agrega_cliente_Click()"
методом, чтобы пользователь знал, из-за чего возникла проблема. Я надеюсь, вы понимаете, что я пытаюсь сделать.
Спасибо
Ответ №1:
Просто избавьтесь от вашей попытки / улова внутри метода AgregaCliente (), и исключение автоматически всплывет.
public bool AgregaCliente(_Cliente cliente, ArrayList refes)
{
Cliente cli = new Cliente()
{
Nombres = cliente.nombres,
ApellidoP = cliente.apellidoP,
ApellidoM = cliente.apellidoM,
FechaNac = cliente.fechaNacimiento
};
if (NombreExiste(cli))
context.clientes.AddObject(cli);
else
throw new System.ArgumentException("El usuario ya existe");
if (refes.Count != 0)
{
foreach (_Referencia elem in refes)
context.referencias_personales.AddObject(AgregaReferencia(elem));
}
context.SaveChanges();
return true;
}
Комментарии:
1. 1 Отличный ответ. Кроме того, если вы хотите что-то сделать с исключением, например, зарегистрировать его, вы можете удалить ‘return false;’ и заменить его на ‘throw;’
2. Кроме того, поскольку функция может только возвращать true или генерировать исключение сейчас, вероятно, вообще нет необходимости в возвращаемом значении bool, и вы можете изменить его на void.
3. Отличный ответ, Дилан, спасибо. Просто чтобы убедиться, что если возникнет другое исключение (например, дубликат ключа в базе данных, неправильный формат и т.д.), Оно также будет скопировано?
4. Это верно, любые необработанные исключения автоматически передаются вызывающему.
Ответ №2:
Проблема в том, что ваш метод AgregaCliente () перехватывает все исключения и просто проглатывает их. Вместо того, чтобы перехватывать все исключения с помощью:
catch (Exception ex)
{
return false;
}
Вы должны перехватывать только определенные исключения, которые вы можете обработать, и позволять остальным проходить по цепочке вызовов. Однако вы должны знать, что генерирование исключений очень «дорого» для программы. C # выполняет большую работу за кулисами, когда генерируется исключение. Лучшим решением может быть использование кода возврата, чтобы указать вызывающим метод AgregaCliente() статус. Например:
public enum AgregaClienteStatus
{
Success = 0;
ClientAlreadyExists = 1;
Other = ??; // Any other status numbers you want
}
public AgregaClienteStatus AgregaCliente(_Cliente cliente, ArrayList refes)
{
Cliente cli = new Cliente()
{
Nombres = cliente.nombres,
ApellidoP = cliente.apellidoP,
ApellidoM = cliente.apellidoM,
FechaNac = cliente.fechaNacimiento
};
if (NombreExiste(cli))
context.clientes.AddObject(cli);
else
return AgregaClienteStatus.ClientAlreadyExists
if (refes.Count != 0)
{
foreach (_Referencia elem in refes)
context.referencias_personales.AddObject(AgregaReferencia(elem));
}
context.SaveChanges();
return AgregaClientStatus.Success;
}
Конечно, эта функциональность также может быть достигнута с использованием постоянных целых чисел, если вам не нравятся перечисления.
Затем вы можете использовать этот возвращаемый статус для указания информации пользователю без затрат на исключение:
var result = AgregaClient(cliente, refes);
switch (result)
{
case AgregaClientStatus.Success:
// Perform success logic
break;
case AgregaClientStatus.ClientAlreadyExists:
MessageBox.Show("Client already exists");
break;
// OTHER SPECIAL CASES
default:
break;
}
}
Комментарии:
1. Хороший ответ, и вы удалили try / catch из метода AgregaCliente, подобного приведенному выше ответу. В случае, если мне понадобится расширить функциональность, я воспользуюсь вашим предложением, спасибо