Я тоже искал решение о том, как отлавливать исключения, выдвигаемые условиями контракта. Это всегда хорошая идея явно бросить исключения, которые могут возникнуть. Хотите ли вы их поймать, чтобы ваш код не останавливался на ударе, зависит от того, какие данные проверены. Я также использую контракты для проверки пользовательского ввода. С помощью предварительных условий контракта вы можете принудительно вводить пользовательский ввод в соответствии с определенными требованиями (например, не нулевой или пустой строкой). Во-вторых, вы можете использовать контракты для проверки собственного внутреннего кода (особенно вычислений) и принудительного применения не только ввода параметров, но и результата действительных расчетов.
Можно отловить исключения, выдвинутые условиями договора ; просто поместите вызывающий код в блок try-catch и явно перехватите тип исключения (исключений), которое будут сгенерированы вашими условиями. Я бы сделал это только с проверкой пользовательского ввода. Потому что , когда условия контракта не только проверяют параметры, но и необходимую логику кода, выдают ошибку ; что-то может быть не так с вашей логикой кода, а не со значениями параметров. В этом случае лучше полностью остановить программу . Но если вы хотите, чтобы ваша программа завершилась более контролируемым образом, вы можете поймать их. Затем вы можете проверить, безопасно ли продолжать работу программы или нет .
И я обнаружил, что также можно проверять нулевые ссылки на события (по крайней мере, созданные вами). Я использовал его в своем собственном примере кода, который также ловит ошибку, выданную контрактом. Вам нужно передать событие или объект, который вызывает событие, в качестве дополнительного параметра для доступа к событию. Следующий код является частью того, что у меня есть в одном из моих классов:
public delegate void Transactie(Rekening rekening);//signature for events
public Transactie RekeningUittreksel;
public Transactie NegatiefSaldo;
public void Storten(decimal bedrag,Transactie actie)
{
Contract.Requires<NullReferenceException>(actie!=null,"\n\nNo event listeners have been added yet!\n\n");
VorigSaldo = Saldo;
Saldo += bedrag;
RekeningUittreksel(this);
}
public void Afhalen(decimal bedrag,Transactie actie,Transactie actie2)
{
Contract.Requires<NullReferenceException>(actie!=null,"\n\nNo event listeners have been added yet!\n\n");
Contract.Requires<NullReferenceException>(actie2 != null, "\n\nNo event listeners have been added yet!\n\n");
VorigSaldo = Saldo;
if (bedrag <= Saldo)
{
Saldo -= bedrag;
RekeningUittreksel(this);
}
else
{
NegatiefSaldo(this);
}
}
Далее - часть основного метода программы. Я закомментировал строки, в которые я добавляю прослушиватели событий, чтобы правила контракта, определенные выше, выдавали исключение nullreference . Вот как их поймать без большого взрыва:
//mijnZichtrekening.RekeningUittreksel += pietjePek.ToonUittreksel;
//mijnZichtrekening.NegatiefSaldo += pietjePek.ToonNegatief;
try
{
mijnZichtrekening.Storten(50m, mijnZichtrekening.RekeningUittreksel);
}
catch (NullReferenceException ex)
{
Console.WriteLine(ex);
}
try
{
mijnZichtrekening.Afhalen(100m, mijnZichtrekening.RekeningUittreksel, mijnZichtrekening.NegatiefSaldo);
}
catch(NullReferenceException ex)
{
Console.WriteLine(ex);
}
Я немного переписал код для проверки нулевых ссылок на события с помощью новых сокращений контракта .NET 4.5:
public void Afhalen(decimal bedrag)
{
NegatiefSaldoHasListeners(this.RekeningUittreksel, this.NegatiefSaldo);//calls the contract abbreviator with delegate type parameters to check for Nullreference
VorigSaldo = Saldo;
if (bedrag <= Saldo)
{
Saldo -= bedrag;
RekeningUittreksel(this);
}
else
{
NegatiefSaldo(this);
}
}
public void Storten(decimal bedrag)
{
UittrekselHasListeners(this.RekeningUittreksel);//calls the contract abbreviator with a delegate type (event) parameter to check for Nullreference
VorigSaldo = Saldo;
Saldo += bedrag;
RekeningUittreksel(this);
}
public virtual void Afbeelden()
{
Console.WriteLine("Rekeningnr: {0:0000 0000 0000 0000}",Nummer);
Console.WriteLine("Saldo: {0}",Saldo);
Console.WriteLine("Creatiedatum: {0:dd-MM-yyyy}",CreatieDatum);
}
[ContractAbbreviator]
public void CheckArgs(string nummer, Klant eigenaar)
{
Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(nummer), "Geen nummer ingevuld!");
Contract.Requires<FormatException>(nummer.Trim().Length == 16,"Ongeldig aantal tekens ingevoerd!");
Contract.Requires<ArgumentException>(!String.IsNullOrWhiteSpace(eigenaar.ToString()), "Eigenaar niet opgegeven!");
}
[ContractAbbreviator]
public void UittrekselHasListeners(Transactie actie)
{
Contract.Requires<NullReferenceException>(actie != null, "\n\nGeen event listener toegewezen!\n\n");
}
[ContractAbbreviator]
public void NegatiefSaldoHasListeners(Transactie actie,Transactie actie2)
{
Contract.Requires<NullReferenceException>(actie != null, "\n\nGeen event listener toegewezen!\n\n");
Contract.Requires<NullReferenceException>(actie2 != null, "\n\nGeen event listener toegewezen!\n\n");
}