Using variable outside Try-Catch - c#

I need to use the value of a variable initialized inside a try block. I have this basic code
Customer customer = null;
try
{
customer = new Customer(....);
}
catch (Exception){}
string customerCode = customer.Code;
If there is no exception, the customer is perfecly usable, but if there is an exception, customer is not initialized, it returns null
I have checked that customer ALLWAYS initializes correctly INSIDE the block. INSIDE It is perfectly usable even in case of exception. But I need it for later use.
Any way to ALLWAYS keep the customer? :)
EDIT:
As you supposed, this was pseudocode. As I can read, it looks like to use exceptions in constructors is a BAD idea. This is part of my REAL code for my constructor.
public class DirectDebitRemmitanceReject
{
int numberOfTransactions;
decimal controlSum;
List<DirectDebitTransactionReject> directDebitTransactionRejects;
public DirectDebitRemmitanceReject(
int numberOfTransactions,
decimal controlSum,
List<DirectDebitTransactionReject> directDebitTransactionRejects)
{
this.numberOfTransactions = numberOfTransactions;
this.controlSum = controlSum;
this.directDebitTransactionRejects = directDebitTransactionRejects;
if (TheProvidedNumberOfTransactionsIsWrong()) ChangeNumberOfTransactionsAndRiseException();
if (TheProvidedControlSumIsWrong()) ChangeControlSumAndRiseException();
}
private bool TheProvidedNumberOfTransactionsIsWrong()
{
return (numberOfTransactions != directDebitTransactionRejects.Count)
}
private bool TheProvidedControlSumIsWrong()
{
return (controlSum !=directDebitTransactionRejects.Select(ddRemmitanceReject => ddRemmitanceReject.Amount).Sum();)
}
private void ChangeNumberOfTransactionsAndRiseException()
{
......
......
throw new ArgumentException(exceptionMessage, "numberOfTransactions")
private void ChangeControlSumAndRiseException()
{
......
......
throw new ArgumentException(exceptionMessage, "controlSum")
}
}
In the methods 'TheProvided...' I check if the arguments are congruent with the sum of values in the list. If not, I update them and inform by raising an ArgumentException
The fact is that I wanted the constructor ALLWAYS returns a valid (congruent) DirectDebitRemmitanceReject, but desired the same constructor to rise the exception if provided wrong numberOfTransactions or controlSum. NumberOfTransactions and controlSum should not be modified later, only readed.
In my tests, this works well
[TestMethod]
[ExpectedException(typeof(System.ArgumentException))]
public void IfTheProvidedControlSumInARemmitanceRejectIsWorgAnExceptionIsThrown()
{
try
{
DirectDebitRemmitanceReject directDebitRemmitanceReject = new DirectDebitRemmitanceReject(
originalDirectDebitRemmitance1MessageID,
2,
100,
directDebitTransactionRejectsList1);
}
catch (System.ArgumentException e)
{
Assert.AreEqual("controlSum", e.ParamName);
Assert.AreEqual("The Control Sum is wrong. Provided: 100. Expected: 150. Initialized with expected value", e.GetMessageWithoutParamName());
throw;
}
}
[TestMethod]
public void IfTheProvidedControlSumInARemmitanceRejectIsWorgItIsCorrected()
{
try
{
DirectDebitRemmitanceReject directDebitRemmitanceReject = new DirectDebitRemmitanceReject(
originalDirectDebitRemmitance1MessageID,
2,
100,
directDebitTransactionRejectsList1);
Assert.AreEqual(150, directDebitRemmitanceReject.ControlSum);
}
catch (ArgumentException) { }
}
But i can,t Assert the directDebitRemmitanceReject.ControlSum outside the 'try' block
So... do I try another aproach (remove the exception from inside the constructor) or is there another workaround?
Thanks! :)
(Sorry for the EXTENSIVE edit) :(

Your example is a perfect illustration of why writing
catch (Exception){}
is a very bad practice.
When you catch an exception, you are supposed to do something about it. If you do not know what to do with an exception in a particular method of your code, don't catch the exception in that method.
If you always need a customer, even when its retrieval causes an exception, add some code to the catch block to set customer variable to some default object:
try {
...
} catch (Exception) {
customer = Customer.Unknown;
}
This assumes that Customer has a property Unknown of type Customer with some default behavior.
Comment: Needed to warn the upper level of my code. Just, when I create an instance, create it, but warn the arguments where wrong. Could you recommend me some better approach?
Make a factory for validating users while creating them:
class CustomerCreationResult {
public Customer Customer() { get; set; }
public CustomerCreationError Error() { get; set; }
}
class CustomerFactory {
public CustomerCreationResult CreateCustomer(String name, int age) { ... }
}
Now you can create your customers as follows:
var r = myCustomerFactory.CreateCustomer(name, age);
if (r.getError() != null) {
... // Present the error
}
Customer customer = r.Customer;
...

If customer always initializes correctly, then why do you have it in the try block?
If you want to persist it when an exception occurs, either move the initialization of customer outside of the try block or use try/catch for smaller chunks of code.
for example:
Customer customer = null;
try
{
//in this block do the stuff that is unlikely to cause exceptions
customer = new Customer(...);
try
{
//stuff that is likely to cause exceptions
}
catch(Exception e)
{
//handle likely errors
}
catch (Exception e)
{
//handle the unusual errors
}

I think 'dasblinkenlight's answer is very good, but for the simplest purpose an if would be enough:
string customerCode = "";
if (customer!=null)
{
customerCode = customer.Code;
}
And you really should check the exception...

Related

Is there an alternative to the Notification pattern for multiple messages and success/failure?

Is there an alternative to the Notification pattern for multiple messages and success/failure?
I have a class, OperationResult, that I use to return a Success boolean and a list of "error" messages. These messages are sometimes unexpected errors but more often ordinary cases that often happen. Sometimes we return single error messages but other times we return several. I'm hoping to find a better way.
This seems to be more or less the Notification pattern advocated by Fowler. The consumers then do something reasonable with the success state and the errors, most often displaying errors to the user but sometimes continuing on in the case of non-fatal errors.
I thus have lots of service methods (not web service methods) that look something like this:
private ThingRepository _repository;
public OperationResult Update(MyThing thing)
{
var result = new OperationResult() { Success = true };
if (thing.Id == null) {
result.AddError("Could not find ID of the thing update.");
return result;
}
OtherThing original = _repository.GetOtherThing(thing.Id);
if (original == null) return result;
if (AnyPropertyDiffers(thing, original))
{
result.Merge(UpdateThing(thing, original));
}
if (result.Success) result.Merge(UpdateThingChildren(thing));
if (!result.HasChanges) return result;
OperationResult recalcResult = _repository.Recalculate(thing);
if (recalcResult.Success) return result;
result.AddErrors(recalcResult.Errors);
return result;
}
private OperationResult UpdateThing(MyThing ) {...}
private OperationResult UpdateThingChildren(MyThing) {...}
private bool AnyPropertyDiffers(MyThing, OtherThing) {...}
As you can imagine, UpdateThing, UpdateThingChildren, and ThingRepository.Recalculate all have similar OperationResult merging/manipulating code interleaved with their business logic.
Is there an alternative to so much code munging around my returned object? I'd like my code to just focus on the business logic without having to be so particular about manipulating an OperationResult.
I'm hoping to instead have code that looks something like the following, something that better expresses its business logic with less message-handling cruft:
public ??? Update(MyThing thing, ???)
{
if (thing.Id == null) return ???;
OtherThing original = _repository.GetOtherThing(thing.originalId);
if (original == null) return ???;
if (AnyPropertyDiffers(thing, original))
{
UpdateThing(thing, original));
}
UpdateThingChildren(thing);
_repository.Recalculate(thing);
return ???;
}
Any ideas?
Note: throwing exceptions isn't really appropriate here as the messages aren't exceptional.
I think this a situation where functional programming can help, so I'd try with a package porting some F# feautures to C#
using Optional;
and since we want to manage exceptions
using Optional.Unsafe;
At this point we can introduce a helper, to do the typical functional "monad chaining"
public static class Wrap<Tin, Tout>
{
public static Option<Tout, Exception> Chain(Tin input, Func<Tin, Tout> f)
{
try
{
return Option.Some<Tout,Exception>(f(input));
}
catch (Exception exc)
{
return Option.None<Tout, Exception>(exc);
}
}
public static Option<Tout, Exception> TryChain(Option<Tin, Exception> input, Func<Tin, Tout> f)
{
return input.Match(
some: value => Chain(value, f),
none: exc => Option.None<Tout, Exception>(exc)
);
}
}
Now, assuming we have the following updates, that can throw exceptions:
Type2 Update1 (Type1 t)
{
var r = new Type2();
// can throw exceptions
return r;
}
Type3 Update2(Type2 t)
{
var r = new Type3();
// can throw exceptions
return r;
}
Type4 Update3(Type3 t)
{
var r = new Type4();
// can throw exceptions
return r;
}
we'll be able to write a logical flow just following the Happy Path
Option<Type4, Exception> HappyPath(Option<Type1, Exception> t1)
{
var t2 = Wrap<Type1,Type2>.TryChain(t1, Update1);
var t3 = Wrap<Type2, Type3>.TryChain(t2, Update2);
return Wrap<Type3, Type4>.TryChain(t3, Update3);
}
Finally, with an extension class like
public static class Extensions {
public static Option<Type2, Exception> TryChain(this Option<Type1, Exception> input, Func<Type1, Type2> f)
{
return Wrap<Type1, Type2>.TryChain(input, f);
}
public static Option<Type3, Exception> TryChain(this Option<Type2, Exception> input, Func<Type2, Type3> f)
{
return Wrap<Type2, Type3>.TryChain(input, f);
}
public static Option<Type4, Exception> TryChain(this Option<Type3, Exception> input, Func<Type3, Type4> f)
{
return Wrap<Type3, Type4>.TryChain(input, f);
}
}
the Happy Path can be written in a beautiful form
Option<Type4, Exception> HappyPath(Option<Type1, Exception> t1)
{
var t2 = t1.TryChain(Update1);
var t3 = t2.TryChain(Update2);
return t3.TryChain(Update3);
}
I would argue that your service is not doing one thing. Its responsible for validating input and then if validation succeeds updating things. And yes I agree that user needs as many information about errors (violations, name not provided, description to long, date end before date start etc) as you can produce on single request and with that the exceptions are not the way to go.
In my projects I tend to separate concerns of validation and update so the service that does the update has little to none chance of failure. Also I like the strategy pattern to do both validation and update - user requests a change the generic service accepts request of validation/update, calls specific validator/updater which in turn calls generic service to validate/update some dependencies. The generic service will merge results and decide upon success or failure of the operation. The obvious benefit is that violation messages merging is done once in some generic class and specific validator/updater can focus on single entity. On the other hand you might want to validate some database uniqueness or existence of objects on the database this exposes two concerns: extra queries to database (light queries that use Exist to minimize output but its a trip to the database) and the latency between validation and update (in that time database can change and your uniqueness or existence verification can change (this time is relatively small but it can happen). This pattern also minimizes duplication of UpdateThingChildren - when you have simple many to many relation the child can be updated from either one of connected entities.
First, to shortly answer your question, there is no alternative to Notification pattern for combining multiple responses into one. Even if you could throw an exception, you'd have AggregateException which is nothing other than Notification pattern for collecting several exceptions into one (exception is just one kind of output that the method can have).
Notification pattern is a great pattern and I don't see a reason to avoid it actually. Yes, your service layer methods look somewhat chatty, indeed, but those could be refactored. While you have not really asked for the advice how this could be refactored, you need to think about that part mostly.
Couple of advises by looking at your code and in general:
It's normal to make Notification pattern a primary pattern in your codebase if applicable. Not just in the service layer, but everywhere else too. If a method returns more than a primitive value as a result, I don't see how else you would do it. So, every method could return OperationResult{TResult} (generic), which indicates the success/failure, as well as the result of the operation - list of errors if failure, TResult object if success. Every caller method will decide what to do with the result - either discard part or all of it, or return it to its caller up in the call stack.
In your code, you have UpdateThingChildren private method. I'm not sure what that does, but it would be much better expressing the intention if you do thing.UpdateChildren() call on the thing itself.
To decrease the chattiness of your service method, you could use fluent interface-like method chaining. It should not be difficult to implement, assuming that every operation you call returns OperationResult. I'd expect your code to look like this at a minimum:
private ThingRepository _repository;
public OperationResult Update(MyThing thing)
{
return new OperationResult() //removed Success = true, just make that a default value.
.Then(() => thing.ValidateId()) //moved id validation into thing
.Then(() => GetOtherThing(thing.Id)) //GetOtherThing validates original is null or not
.Then(() => thing.AnyPropertyDiffersFrom(original)) //moved AnyPropertyDiffers into thing
.Then(() => thing.UpdateChildren())
.Then(() => _repository.Recalculate(thing));
}
private OperationResult GetOtherThing(MyThing ) {...}
As you can imagine, implementing Then method is not difficult at all. It's defined on OperationResult and takes Func{OperationResult} (generic) as argument. It does not execute func if success == false. Otherwise, it executes func and merges the operation result with itself. At the end, it always returns itself (this).
Some people understand that patterns are not to be broken. But patterns have many critics. And there is really room for improvisation. You still can consider that you have implemented a pattern even if you modified some details. Pattern is general thing and can have specific implementation.
Saying that, you can choose not to go with such fine-grained operation result parsing. I always advocated for something like this pseudo-code
class OperationResult<T>
{
List<T> ResultData {get; set;}
string Error {get; set;}
bool Success {get; set;}
}
class Consumer<T>
{
void Load(id)
{
OperationResult<T> res = _repository.GetSomeData<T>(id);
if (!res.Success)
{
MessageBox.Show(DecorateMsg(res.Error));
return;
}
}
}
As you see, server code return data or error message. Simple. Server code does all the logging, you can write errors to DB, whatever. But I see no value passing complex operation results to consumer. Consumer only needs to know, success or not. Also, if you get multiple things in same operation, what the sense to continue operation if you fail get first thing? May be the problem that you trying to do too many things at once? It is arguable. You can do this
class OperationResult
{
List<type1> ResultData1 {get; set;}
List<type2> ResultData2 {get; set;}
List<type3> ResultData3 {get; set;}
string[] Error {get; set;} // string[3]
bool Success {get; set;}
}
In this case you may fill 2 grids but not third one. And if any errors occur on client side because of this, you will need to handle it with client error handling.
You definitely should feel free to adjust any patterns for your specific needs.
I see two possible options that you could use while avoiding throwing exceptions, but in the end we are only reducing the amount of code needed for messages:
I would refactor the code a little bit in order to make it more standard across all calls. Like the following (See comments inside the parenthesis in the code comments):
public OperationResult Update2(MyThing thing)
{
var original = _repository.GetOtherThing(thing.Id);
if (original == null)
{
return OperationResult.FromError("Invalid or ID not found of the thing update.");
}
var result = new OperationResult() { Success = true };
if (AnyPropertyDiffers(thing, original))
{
result.Merge(UpdateThing(thing, original));
if (!result.HasChanges) return result;
}
result.Merge(UpdateThingChildren(thing));
if (!result.HasChanges) return result;
result.Merge(_repository.Recalculate(thing));
return result;
}
_repository.GetOtherThing - Delegate Id checking to the repository, for simpler code and to ensure we return an error if nothing happened
UpdateThing - With exit after no changes
_repository.Recalculate - We now merge results and return them
Use a scope class shared by all the services at the construction of the services.
// We a scope class shared by all services,
// we don't need to create a result or decide what result to use.
// It is more whether it worked or didn't
public void UpdateWithScope(MyThing thing)
{
var original = _repository.GetOtherThing(thing.Id);
if (_workScope.HasErrors) return;
if (original == null)
{
_workScope.AddError("Invalid or ID not found of the thing update.");
return;
}
if (AnyPropertyDiffers(thing, original))
{
UpdateThing(thing, original);
if (_workScope.HasErrors) return;
}
UpdateThingChildren(thing);
if (_workScope.HasErrors) return;
_repository.Recalculate(thing);
}
_repository.GetOtherThing must add any errors to the _workScope
UpdateThing must add any errors to the _workScope
UpdateThingChildren must add any errors to the _workScope
_repository.Recalculate must add any errors to the _workScope
In this last example we don't need to return anything since the caller will have to verify if the scope is still valid.
Now if there are multiple validations to be performed I would suggest doing another class like Rafal mentioned.
Last note: I would throw exceptions for anything that should be handled in the GUI like the 'thing.Id' sent without a value or not sent at all, that sounds to me like whoever did the interface didn't handle this scenario properly or the current interface is old or unsupported, which normally is enough reason to throw an exception.
You can use exceptions internally without throwing them to callers. This allows you to break out of a failed operation easily, and groups your business logic all in one place. There is still some 'cruft', but it's separated (and could be in its own class) from the business logic, which is contained in the *Internal implementations. Not saying this is the best or only way of approaching this problem, but I may go with this:
public class OperationResult
{
public bool Success { get; set; }
public List<string> Errors { get; set; } = new List<string>();
}
public class Thing { public string Id { get; set; } }
public class OperationException : Exception
{
public OperationException(string error = null)
{
if (error != null)
Errors.Add(error);
}
public List<string> Errors { get; set; } = new List<string>();
}
public class Operation
{
public OperationResult Update(Thing thing)
{
var result = new OperationResult { Success = true };
try
{
UpdateInternal(thing);
}
catch(OperationException e)
{
result.Success = false;
result.Errors = e.Errors;
}
return result;
}
private void UpdateInternal(Thing thing)
{
if (thing.Id == null)
throw new OperationException("Could not find ID of the thing update.");
var original = _repository.GetOtherThing(thing.Id);
if (original == null)
return;
if (AnyPropertyDiffers(thing, original))
result.Merge(UpdateThing(thing, original));
result.Merge(UpdateThingChildren(thing));
if (result.HasChanges)
_repository.Recalculate(thing);
}
}
I would approach with State pattern and internal collection to save information. You can start applying events that change the state and store the information related to the applied event. Finally call get information to wrap them inside operationresult.
A pseudo code
public OperationResult Update(MyThing thing)
{
return new OperationResult
{
Errors = thing.ApplyEvent(Event.NullCheck)
.ApplyEvent(Event.OriginalNullCheck)
.ApplyEvent(Event.OriginalPropertyDiffersCheck)
.CollectInfo(),
Success = true
};
}
public class MyThing
{
private List<string> _errors = new List<string>();
private MyThing _original;
public MyThingState ThingState {get;set;}
public MyThing ApplyEvent(Event eventInfo)
{
MyThingState.ApplyEvent(this, eventInfo)
}
}
public class NullState : MyThingState
{
public MyThing ApplyEvent(MyThing myThing, Event eventInfo)
{
if(mything == null)
{
// use null object pattern
mything.AddErrors("Null value")
// Based on the event, you select which state to instantiate
// and inject dependencies
mything.State = new OriginalNullState();
}
}
}
public class OriginalNullState : MyThingState
{
public void ApplyEvent(MyThing myThing, Event eventInfo)
{
// Get original from database or repository
// Save and validate null
// Store relevant information in _errors;
// Change state
}
}
Even though I would have loved throwing exception, here it is not appropriate because you are not in fail-fast. You are taking corrective measures on non fatal cases. You just want higher layers to know about it.
public OperationResult<DataSet> Update(MyThing thing, OperationResult<DataSet> papa)
{
// Either you have a result object from enclosing block or you have null.
var result = OperationResult<DataSet>.Create(papa);
if (thing.Id == null) return result.Fail("id is null");
OtherThing original = _repository.GetOtherThing(thing.originalId);
if (original == null) return result.warn("Item already deleted");
if (AnyPropertyDiffers(thing, original))
{
UpdateThing(thing, original, result));
// Inside UpdateThing, take result in papa and do this dance once:
// var result = OperationResult<DataSet>.Create(papa);
}
UpdateThingChildren(thing, result);
// same dance. This adds one line per method of overhead. Eliminates Merge thingy
_repository.Recalculate(thing, result);
return result.ok();
}
You can eliminate passing result everywhere using Scope pattern from #BigShot, but i personally do not like ambient contexts. The could be anything you may need to return back.
class OperationResult<T> {
enum SuccessLevel { OK, WARN, FAIL }
private SuccessLevel _level = SuccessLevel.OK;
private List<String> _msgs = new ...
public T value {get; set};
public static OperationResult<T> Create(OperationResult<T> papa) {
return papa==null ? new OperationResult<T>() : papa;
}
public OperationResult<T> Fail(string msg) {
_level = SuccessLevel.Fail;
_msgs.add(msg);
return this; // this return self trick will help in reducing many extra lines in main code.
}
// similarly do for Ok() and Warn()
}

Inheritance and Exception Handling

I am trying to complete a homework assignment however I am not sure what to do next. I have been struggling with Inheritance and Exception Handling...this problem combines the two.
Could you please give me a shove in the right direction?
Here is the question:
Create a program named BookExceptionDemo for the Peterman Publishing Company. The company has decided that no published book should cost more than 10 cents per page. Create a BookException class whose constructor requires three arguments: a string Book title, a double price, and an int number of pages. Create an error message that is passed to the Exception class constructor for the Message property when a book does not meet the price-to-page ratio. For example, an error message might be:
For Goodnight Moon, ratio is invalid.
...Price is $12.99 for 25 pages.
Create a Book class that contains fields for title, author, price, and number of pages. Include properties for each field. throw a BookException if a client program tries to construct a Book object for which the price is more than 10 cents per page. Create a program that creates at least four Book objects - some where the ratio is acceptable and others where it is not. Catch any thrown exceptions and display the BookException Message.
Here is what I have so far:
namespace BookExceptionDemo
{
class BookException : Exception
{
public BookException(string title, double price, int numberPages)
: base("For " + title + ", ratio is invalid. \nPrice is $" + price + " for " + numberPages + " pages.") //p.470
{
}
}
class Book
{
public Book(string title, double price, int numberPages) //he said this should check to see if the ratio is correct, if not, then throw exception.
{
}
public string Title { get; private set; }
public double Price { get; private set; }
public int NumberPages { get; private set; }
}
// my teacher put this here
// but at the end of class he said the contents should be moved somewhere else?
// Does it go in the BookException constructor?
class Program
{
static void Main(string[] args)
{
try
{
throw (new BookException("Goodnight Moon", 12.99, 25));
}
catch (BookException e)
{
Console.WriteLine(e.Message);
}
Console.Read();
}
}
}
EDIT
My school switched programming languages this semester, so I came into this intermediate C# course with no prior knowledge of the language. I understood most things up until the past few class sessions. I was getting frustrated in my confusion and was feeling disheartened, but now I can honestly say that I am excited to have a better understanding of these concepts. Programming is really fun and I really appreciate people like you who are willing to help others. Thank you all for the time and effort you have given in assisting me.
Here is what I believe to be the correct answer to the question I posted.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BookExceptionDemo
{
class BookException : Exception
{
public BookException(string title, double price, int numberPages)
: base("For " + title + ", ratio is invalid. \nPrice is $" + price + " for " + numberPages + " pages.")
{
}
}
class Book
{
public Book(string title, string author, double price, int numberPages)
{
if ((price / numberPages) > .1)
{
throw new BookException(title, price, numberPages);
}
}
private string title;
private string author;
private double price;
private int numberPages;
public string Title
{
get
{
return title;
}
set
{
title = value;
}
}
public string Author
{
get
{
return author;
}
set
{
author = value;
}
}
public double Price
{
get
{
return price;
}
set
{
price = value;
}
}
public int NumberPages
{
get
{
return numberPages;
}
set
{
numberPages = value;
}
}
}
class Program
{
static void Main(string[] args)
{
try
{
Book junglebook = new Book("Jungle Book","Kipling", 25.99, 50); //should throw exception
}
catch (BookException ex)
{
Console.WriteLine(ex.Message);
}
try
{
Book hobbit = new Book("The Hobbit","Tolkien", 2.99, 30); //should NOT throw exception
}
catch (BookException ex)
{
Console.WriteLine(ex.Message);
}
try
{
Book book1984 = new Book("1984","Orwell", 31.32, 15); //should throw exception
}
catch (BookException ex)
{
Console.WriteLine(ex.Message);
}
try
{
Book guidetonetworks = new Book("Guide to Networks","Somebody", 17.56, 500); //should NOT throw exception
}
catch (BookException ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
}
}
The concept of exceptions is that something really bad has happened. So bad that you are interrupting the control flow of the program.
In this case, you need to throw as (effectively) a validation step when creating a book. The check needs to happen on book creation, so we put it in the constructor:
public Book(string title, double price, int numberPages)
{
bool goodPrice = true; //Actual condition left as an exercise
if (!goodPrice) //No good, bail!
throw new BookException(title, price, numberPages);
}
The calling code will need to wrap any invocations of Books constructor in a try/catch to handle this. Be aware that a thrown exception breaks normal control flow, the catch block is immediately entered and control is not returned to the try block.
The Program class and indeed all these classes, typically reside in their own files, which is possibly what your instructor was alluding to by saying it would normally be somewhere else.
Regardless, you already know how to invoke a constructor (through instantiation, you did it for the exception!). Now you just need to create a few Book objects (some with invalid parameters). With the code given, the Main method makes sense for this.
A sample call would look like:
try
{
Book introToC = new Book("C# is Awesome!", 10.00, 100);
}
catch (BookException ex) //Specify what we are catching!
{
//Do something, in your case print. (Left as exercise).
}
Update
To your question about why we use try/catch. First, I suggest you ask your instructor, as he will explain it better than I can :).
However, try to imagine your objects as actual objects and it makes a bit more sense. Suppose I had a "SuperBigButton" class with a "Click" method. In real terms, its a super big button I can push.
Suppose I then push that button, but I forgot to turn it on (I'm not terribly bright in this example). Now, the thing attached to the button could just print out an error message, or even do nothing, but the point is I don't know anything is wrong.
It is better if it punches me in the face, saying "You didn't turn it on!". This is much more useful to me (the calling code). Certainly there are patterns where bool return values are used instead of exceptions (the TryParse family of functions come to mind) but this is why we use exceptions. We need to be able to "error out" and tell the calling code something is broken.
Exceptions also have the advantage of interrupting the control flow, so anything in the calling code that depended on the given call succeeding will not run (they are skipped as control moves to the catch block).
public Book(string title, double price, int numberPages)
{
if(price / numberPages > 0.1)
throw new BookException(title, price, numberPages);
}

Pass object (List<string>) as part of Exception

I am constructing a list of strings and then want to throw an exception and let the UI handle the list and create the error message for the user.
Is there a way to do that?
Exceptions contains Data property (which is a dictionary). It can be used to pass additional information:
try
{
// throw new Exception
}
catch(Exception e)
{
// whatever
e.Data["SomeData"] = new List<string>();
}
You can use the Exception.Data property to pass arbitrary data but a better (cleaner) solution would be to create your own custom exception class derived from Exception and add whatever properties you need to it.
Sample code:
public class MyException: Exception
{
public List<String> MyStrings { get; private set; }
public MyException(List<String> myStrings)
{
this.MyStrings = myStrings;
}
}

If I throw an exception in a getter of a property, can I obtain the name of the property in a catch block?

If I throw an exception from a getter of a property, is it possible to obtain the name of
the property in the catch block where I have called that property -like using reflection or
reading the stack trace?
For instance:
class Animal
{
private string _name;
public string Name {
get { throw new Exception(); }
set { _name = value; }
}
}
And in another place, I call the Name property's getter and I want to obtain the property name in the catch block:
Animal cat = new Animal();
try{
string catName = cat.Name;
}
catch (Exception e)
{
string propertyName = //Here I should be able to reach "Name"
}
it will show in your stack trace as exception in get_Name() method. you can probably parse it to get the Property Name
There are two options, non of which are great:
Parse the get_Name() method from the Exception.StackTrace property, as Ashley and Mongus describe. This will fail when the getter gets inlined (which is not unlikely to happen), because inlined methods calls will (obviously) not show up in the stacktrace.
Throw a special exception that contains that property name:
public string PropertyName
{
get { throw new PropertyException("PropertyName", "Ex message.");
}
This however isn't great either, since you should explicitly throw this type of exception. So failures from deeper down the callstack must be wrapped in that PropertyException.
You could parse e.StackTrace using a Regex :
try
{
int x = this.Ong;
}
catch ( Exception ex )
{
Console.WriteLine ( Regex.Match ( ex.StackTrace, #"get_(?<prop>.*)\(\)" ).Groups["prop"].Value );
}
Note You should put more error checking on the Regex above as Groups["prop"] may be null if the exception isn't raised from a property.
If you're considering something like this you most likely would be far better off implementing something like the INotifyPropertyChanged and stick this as part of your getter instead of only caring about the setter like normal usage.
How to: Implement the INotifyPropertyChanged Interface
Exception.TargetSite
Since C# 5, you can use CallerMemberNameAttribute.
public class SomeCustomException : Exception
{
public string PropertyName { get; }
public SomeCustomException(string propertyName)
: base($"Property {propertyName} was null)
{
this.PropertyName = propertyName;
}
}
public class Animal
{
public string Name
{
get { Throw(); }
}
private static void Throw([CallerMemberName] string propertyName = null)
{
// propertyName will be 'Name'
throw new CustomException(propertyName);
}
}
I could have put [CallerMemberName] directly on the constructor for SomeCustomException, but that seems unnecessarily ugly: the exception doens't need to know that it will be called from the property getter, hence the separate static Throw method.

General Business Object Practices (and exception errors - redux)

Recently, I made a post about the developers I'm working with not using try catch blocks properly, and unfortuantely using try... catch blocks in critical situations and ignoring the exception error all together. causing me major heart ache. Here is an example of one of the several thousand sections of code that they did this (some code left out that doesn't particuarly matter:
public void AddLocations(BOLocation objBllLocations)
{
try
{
dbManager.Open();
if (objBllLocations.StateID != 0)
{
// about 20 Paramters added to dbManager here
}
else
{
// about 19 Paramters added here
}
dbManager.ExecuteNonQuery(CommandType.StoredProcedure, "ULOCATIONS.AddLocations");
}
catch (Exception ex)
{
}
finally
{
dbManager.Dispose();
}
}
This is absolutely discusting, in my eyes, and does not notify the user in case some potential problem occurred. I know many people say that OOP is evil, and that adding multiple layers adds to the number of lines of code and to the complexity of the program, leading to possible issues with code maintainence. Much of my programming background, I personally, have taken almost the same approach in this area. Below I have listed out a basic structure of the way I normally code in such a situation, and I've been doing this accross many languages in my career, but this particular code is in C#. But the code below is a good basic idea of how I use the Objects, it seems to work for me, but since this is a good source of some fairly inteligent programming mines, I'd like to know If I should re-evaluate this technique that I've used for so many years. Mainly, because, in the next few weeks, i'm going to be plunging into the not so good code from the outsourced developers and modifying huge sections of code. i'd like to do it as well as possible. sorry for the long code reference.
// *******************************************************************************************
/// <summary>
/// Summary description for BaseBusinessObject
/// </summary>
/// <remarks>
/// Base Class allowing me to do basic function on a Busines Object
/// </remarks>
public class BaseBusinessObject : Object, System.Runtime.Serialization.ISerializable
{
public enum DBCode
{ DBUnknownError,
DBNotSaved,
DBOK
}
// private fields, public properties
public int m_id = -1;
public int ID { get { return m_id; } set { m_id = value; } }
private int m_errorCode = 0;
public int ErrorCode { get { return m_errorCode; } set { m_errorCode = value; } }
private string m_errorMsg = "";
public string ErrorMessage { get { return m_errorMsg; } set { m_errorMsg = value; } }
private Exception m_LastException = null;
public Exception LastException { get { return m_LastException; } set { m_LastException = value;} }
//Constructors
public BaseBusinessObject()
{
Initialize();
}
public BaseBusinessObject(int iID)
{
Initialize();
FillByID(iID);
}
// methods
protected void Initialize()
{
Clear();
Object_OnInit();
// Other Initializable code here
}
public void ClearErrors()
{
m_errorCode = 0; m_errorMsg = ""; m_LastException = null;
}
void System.Runtime.Serialization.ISerializable.GetObjectData(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
{
//Serialization code for Object must be implemented here
}
// overrideable methods
protected virtual void Object_OnInit()
{
// User can override to add additional initialization stuff.
}
public virtual BaseBusinessObject FillByID(int iID)
{
throw new NotImplementedException("method FillByID Must be implemented");
}
public virtual void Clear()
{
throw new NotImplementedException("method Clear Must be implemented");
}
public virtual DBCode Save()
{
throw new NotImplementedException("method Save Must be implemented");
}
}
// *******************************************************************************************
/// <summary>
/// Example Class that might be based off of a Base Business Object
/// </summary>
/// <remarks>
/// Class for holding all the information about a Customer
/// </remarks>
public class BLLCustomer : BaseBusinessObject
{
// ***************************************
// put field members here other than the ID
private string m_name = "";
public string Name { get { return m_name; } set { m_name = value; } }
public override void Clear()
{
m_id = -1;
m_name = "";
}
public override BaseBusinessObject FillByID(int iID)
{
Clear();
try
{
// usually accessing a DataLayerObject,
//to select a database record
}
catch (Exception Ex)
{
Clear();
LastException = Ex;
// I can have many different exception, this is usually an enum
ErrorCode = 3;
ErrorMessage = "Customer couldn't be loaded";
}
return this;
}
public override DBCode Save()
{
DBCode ret = DBCode.DBUnknownError;
try
{
// usually accessing a DataLayerObject,
//to save a database record
ret = DBCode.DBOK;
}
catch (Exception Ex)
{
LastException = Ex;
// I can have many different exception, this is usually an enum
// i do not usually use just a General Exeption
ErrorCode = 3;
ErrorMessage = "some really weird error happened, customer not saved";
ret = DBCode.DBNotSaved;
}
return ret;
}
}
// *******************************************************************************************
// Example of how it's used on an asp page..
protected void Page_Load(object sender, EventArgs e)
{
// Simplifying this a bit, normally, I'd use something like,
// using some sort of static "factory" method
// BaseObject.NewBusinessObject(typeof(BLLCustomer)).FillByID(34);
BLLCustomer cust = ((BLLCustomer)new BLLCustomer()).FillByID(34);
if (cust.ErrorCode != 0)
{
// There was an error.. Error message is in
//cust.ErrorMessage
// some sort of internal error code is in
//cust.ErrorCode
// Give the users some sort of message through and asp:Label..
// probably based off of cust.ErrorMessage
//log can be handled in the data, business layer... or whatever
lab.ErrorText = cust.ErrorMessage;
}
else
{
// continue using the object, to fill in text boxes,
// literals or whatever.
this.labID = cust.ID.toString();
this.labCompName = cust.Name;
}
}
Bottom line, my question is, Am I over complicating things with the muliple layers, and the inherited classes or is my old concept illustrated still working good and stable? Is there a better way now a days to accomplish these things? Should I go to just making straight SQL calls from the asp.net page code behind pages as fellow work associate developer suggested (though that last solution makes me feel icky), instead of going through a business object, and data layer (data layer not shown, but basically holds all the stored proc calls). Yeah, another developer did ask me why i go through the effort of layering things, when you can just type what you need straight in a *.aspx.cs code behind page, and then I can have the joys of over 1k lines of code behind. What is some advice here?
Have you considered using an ORM like NHibernate? There's no point in re-inventing the wheel.
To me this is a code smell:
BLLCustomer cust = ((BLLCustomer)new BLLCustomer()).FillByID(34);
Too many brackets!
I've found that using the active record pattern in a language like C# always ends in tears because it's hard(er) to unit test.
The jump from the first bit of code to the next is huge. Whether a complicated business object layer is necessary will depend on the size of the app in question. At the very least though our policy is that exceptions are logged where they are handled. How you present to the user is up to you but having logs is essential so that developers can get more information if necessary.
Why not just catch the exception in the Page_Load event? Some exception you might expect and know how to deal with, other exceptions should be handled by a global exception handler.
My rule of thumb is to only catch errors that I can handle or give the user something useful so that if they do whatever it was they did again, it is likely to work for them. I catch database exceptions; but only to add some more information onto the error about the data being used; then I re-throw it. The best way to handle errors in general is to not catch them at all anywhere but at the top of the UI stack. Just having one page to handle the errors and using the global.asax to route to it handles almost all situations. Using status codes is definitely out of style all together. It is a remnant of COM.
Is it possible to use an abstract base class instead of a concrete class? this would force the implementation of your methods at development time rather than runtime exceptions.
The best comment here to agree with is from dances, where you should only handle exceptions you can recover from at that point. Catching others and rethrowing is the best method (although i think its rarely done). Also, make sure they are logged.... :)
YOur way of errorhandling seems very outdated. Just make a new exeption and inherit from exeption that way you have the callstack at least. Then you should log with something like nlog or log4net. And this is the year 2008 so use generics. You will have to do a lot less casting that way.
ANd use an ORM like someone said before. Don't try to reinvent the wheel.

Categories