This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Direct casting vs 'as' operator?
Where could this operator be useful? Instead of writing this:
Asset a = new Asset();
Stock s = a as Stock; // s is null; no exception thrown
if (s != null) Console.WriteLine (s.SharesOwned);
You'd better write something that throws. I saw tons of
(s != null)
in production code and it really becomes ugly. Exceptions are more descriptive and natural in that way. Even conceptually: how can you get no asset if it is not a stock? It should an exception if it is not a stock.
You often have the case where you don’t want an exception to be thrown because, well, the situation isn’t exceptional. You have a frob object which you know can be a Foo, but could also be a Bar. So you want to perform some action only if it’s a Foo.
You try to avoid these situations in designs, and use virtual methods instead. But sometimes there’s just no good way around that.
So rather than taking the roundabout way,
if (frob is Foo) {
((Foo) frob).Frobnicate();
}
you do it directly:
var asFoo = frob as Foo;
if (asFoo != null) {
asFoo.Frobnicate();
}
If nothing else, this is at least more efficient since you only need to test for type equality once (inside the as cast) instead of twice (in the is and in the cast).
As a concrete example, this is very useful when you want to clear all the input boxes in a form. You could use the following code:
foreach (Control c in this.Controls) {
var tb = c As TextBox;
if (tb != null)
tb.Clear();
}
Using an exception here would make no sense.
You'd better write something that throws
Not necessarily. Users don't like seeing things throwing. You should write code that works. And if it doesn't you'd better handle it appropriately by apologizing to the user. The as operator can be useful in situations where for example you would attempt a cast and if this cast doesn't work assign a default value to the variable so that the code continues to work with this default value. It would really depend on the context.
as does an is and if the is returns false assigns null.
sounds like a song but it's the answer and I use it a lot, like in the FindControl methods of ASP.NET:
Button myButton = e.item.FindControl("myControlId") as Button;
this kind of assignment does not crash or throw simply assigns null if FindControl finds something different than a Button. I like this so much....
If Asset is inherited from Stock, then this should be fine. That's the only sort of case where I've seen that work, although you could prolly also use it in the case of interfaces.
Yes, the as operator is useful, and yes, it can be misused.
If you are sure that some variable x is of type T, you should use a regular cast.
T y = (T)x;
If both T1 and T2 are valid types for variable x, you cau use as to check the type and perform the cast in one operation.
What are your requirements?
If the asset is a stock print the number of shares owned.
The as operator is very useful in that case but you will have to check stock != null. That is implied by the requirement.
Print the number of shares owned of a stock. It is an error if another asset is supplied.
Then you should write code that throws an exception.
Exceptions are not designed for flow control, they are, by definition, exceptions to the normal train of events. If it's acceptable for the conversion to fail, use as. If, rather, not being able to cast "a" as a Stock should never happen, you can use simple s=(Stock)a; which will throw it's own exception. You have no control of the exception at this point, though.
The following lets the developer handle the exceptional case much cleaner:
Asset a= new Asset();
Stock s= a as Stock();
if(s == null) {
// Safely exit from call if possible, maybe make calls to logging mechanism or
// other ways of determining why an exception occurred. Also, could throw custom
// Exception if needed with much more detailed info.
} else {
// Continue normal flow
}
You could do:
Asset a= new Asset();
try
{
Stock s= (Stock);
// Continue normal flow
}
catch (InvalidCastException exc)
{
// Safely exit from call if possible, maybe make calls to logging mechanism or
// other ways of determining why an exception occurred. Also, could throw custom
// Exception if needed with much more detailed info.
}
However, that is using the exception as flow control and is costly and bad design.
It depends on your Error Handling policy. I work on code base where we always use casting than using as operator. However, there are some cases where AS operator is very much useful and faster than exception.
For example,
In following case what do you What do you prefer?
public bool Process(int choice)
{
try
{
Thing thing = GetRequiredThing(choice);
SubThing subThing = (SubThing)thing;
}
catch (InvalidCastException ex)
{
// report ex.
return false;
}
}
or
public bool Process(int choice)
{
Thing thing = GetRequiredThing(choice);
SubThing subThing = thing as SubThing;
if (subThing == null)
{
//report error;
return false;
}
}
If is not necessary that you should always use as operator. Take your call.
Related
I'm so used to check if a method's argument is null (then proceed to throw an exception) that I almost don't even think about it anymore.
If the argument is a reference type, it's there:
if(arg == null)
throw new ArgumentNullException(nameof(arg));
But what if I'm going to use arg immediately? Should I check anyway? I mean, if I don't, the envinroment will throw for me (a NullReferenceException) anyway.
For instance:
public int DoStuff(object o)
{
return o.GetHashCode();
}
I could write add the null check easily:
public int DoStuff(object o)
{
if(o == null)
throw new ArgumentNullException(nameof(o));
return o.GetHashCode();
}
But in both cases a exception will be thrown (in almost the exact same line, for debugging purpose). The only difference is the type.
The question: On public methods with a single reference type argument, if I'm going to use the argument immediately, should I still check it if it's null?
I suggest checking, because you have two Exception types:
Unexpected NullReferenceException - something went wrong, and you have to debug your own routine
ArgumentNullException - the argument is null, and it's caller that's wrong (and not your code which reacts right)
throwing ArgumentNullException is kind of contract: I'll do the thing in case argument is correct:
// An exaggerated example
public int DoStuff(SomeObject o) {
if (o == null)
throw new ArgumentNullException(nameof(o));
else if (o.Disposed)
throw new ArgumentException(nameof(o), "o must not be disposed")
else if (o.Id > 100)
throw new ArgumentOutOfRangeException("Id ...", nameof(o));
// o meets the contract, we accept it and thus we guarantee the output
return o.SomeMethod();
}
This kind of validation is typical for public (protected) methods since they're exposed to outer world and can face any argument; however, in case of private method you can omit the contract: any caller is within the class that implements the method.
Well, it depends ;)
This is my take on it, and the question is (kinda) subjective.
IMO, if the code throws a NullReferenceException, it means that the code itself has no internal consistency. It is a sign of lazyness and should be avoided at all costs.
If a method throws a NullReferenceException, it is method's fault.
An ArgumentNullException, on the other hand, means that the method cannot "do it's stuff" if the argument is null.
It becomes responsibility of the invoker to guarantee that the parameter is not null, or handle graciously the exception.
Bottom line: an ArgumentNullException is a contract, a NullReferenceException is a bug.
I suppose if you are immediately dereferencing the variable, you could debate either way, but I would still prefer the ArgumentNullException.
It is much more explicit about what is going on. The exception contains the name of the variable that was null, whereas a NullReferenceException does not.
I strongly suggest you check for null at the top of the method.
Think of that as a "contract" that specifies the following:
In order for this method to execute, this argument must be non-null.
Doing the null check is great documentation. You could go one step further an use XML comments e.g.
/// <summary>
///
/// </summary>
/// <param name="arg1"></param>
/// <exception cref="ArgumentNullException">If <paramref name="arg1"/> is NULL.</exception>
private static void Foo(object arg1)
{
}
I'd say it depends more on how you handle the errors, not how they're thrown. An example will help. Imagine this is the method instead of what you have:
public static int DoStuff(string o) {
return Int.Parse(o);
}
If you have this, then it really doesn't matter.
public static void main(string[] args)
{
try {
Console.Write("Enter a number: ");
value = DoStuff(Console.ReadLine());
}
catch(Exception ex) {
Console.WriteLine("An exception was thrown. Contents: " + ex.ToString());
}
}
Either way your program flow is the same. But if you have below:
public static void main(string[] args)
{
try {
int value = 0;
do {
try {
Console.Write("Enter a non-zero number to stop: ");
value = DoStuff(Console.ReadLine());
}
catch(ArgumentException ex) {
Console.WriteLine("Problem with input, try again. Exception message was: " + ex.Message);
continue; // Or just nothing, will still loop
}
} while(value == 0);
}
catch(Exception ex) {
Console.WriteLine("An exception was thrown. Contents: " + ex.ToString());
}
}
Basically, if your error handling doesn't care which exception type it is, then it's just extra code that probably doesn't help you. But if you handle specific things differently, then it may be worth it to test and throw the more specific type of exception.
But I do agree with Dmitry's post above that a public method matters a lot more than a private one. Your signature for the method is somewhat like a contract. It's best to enforce it.
There are a few different scenario's I think you should consider:
The method is called from your own program. You don't expect a null value. You use the object somewhere down the line and if it's null, it will still change the state.
The method is called from your own program. You don't expect a null value. If it's a null, it won't change the state and everything will continue to be consistent.
The method is exposed through a library or API. An unknown developer X calls the method with whatever you want.
You just want to know that an argument is not null while implementing stuff. To protect yourself and your team members.
Points (1) and (2) are about exception safety. Basically this states that regardless of your input, the state of your data structures should be consistent. In most cases this is resolved through a simple check; in more complex scenario's it might involve a rollback or a more complex piece of machinery. So:
If you add a null value to a database, you don't want it to mess up your database. Now, you can of course solve null values by simply checking your assumption. If the argument is null, throw an ArgumentNullException because that best describes the scenario.
If you call a method that doesn't expect a null value and it won't influence the rest of your system, I usually put a comment somewhere and let nature run its course. A NullReferenceException tells me enough about the nature of the bug.
If it's an API, people expect certain behavior (e.g. a ArgumentNullException). Moreover, as a developer you shouldn't trust the big bad outside world so you should check anyways.
If you just want to protect yourself and your team members, use an Assertion. Assertions are usually implemented in such a way, that they don't end up in release code (or at least have no impact on your speed), will automatically trigger a breakpoint and will fail your unit test. They're also easy to recognize so they won't add too much bloat to your code.
To summarize, I wouldn't just put checks everywhere; they tend to make your code unreadable and bloaty. That said, if I would put a check to ensure exception safety, it's best to use the exception that best describes the error.
Follow Einstein - "make things as simple as possible, but no simpler". Does that code do the same thing without a line of code? If so, it is probably best to remove it.
I am writing a method (for a service) that returns a specific error code to the client.
Inside this method I am calling various LINQ extension methods. Each one of these extension methods can throw exceptions of 'same' type (say InvalidOperationException), but I need to catch these exceptions individually and return a specific error code. Here is what it looks like now (much simplified version)
public errorCode SomeMethod()
{
try
{
var foo1 = SomeDataSource.Entities1.Single(x=> x.bar1 == somevalue);
}
catch(InvalidOperationException x)
{
return ErrorCode1;
}
try
{
var foo2 = SomeDataSource.Entities2.Single(x=> x.bar2 > somevalue);
}
catch(InvalidOperationException x)
{
return ErrorCode2;
}
......
This is adding up to be a lot of try-catch blocks, as there are several error conditions that can potentially exist. It is also forcing me to elevate the scope of variables like foo to outside the individual try blocks, as they are being used in subsequent try blocks.
I am just curious to see if there is a way to consolidate all this code in a more elegant manner (some inline methods perhaps?) so that it doesn't end up looking so intimidating?
Based on the feed back I got, I have to add that the Business Rules that I am trying to implement leads me to use 'Single' and not 'SingleOrDefault'. Using 'SingleOrDefault' makes it easier because then we can just check for null without catching the exception. 'Single' on the other hand simply throws an exception if the condition fails. Idea here is to consolidate all these try blocks where as somehow keep all the errors happening separate even though every call to 'Single' throws the same type of exception (InvalidOperationException)...
Thanks
You are misusing exceptions for control flow. Better:
var foo1 = SomeDataSource.Entities1.SingleOrDefault(x=> x.bar1 == somevalue);
if (foo1 == null) return ErrorCode1;
Very clean and simple.
What's especially vexing in the original code is that you are treating all occurrences of InvalidOperationException as the same thing. Who knows whether that's true or not?! There can be many things throwing this particular exception type. You might hide bugs by catching too generously. You might even hide EF bugs this way.
If you want to move your business logic into the lambda method, which it sounds like, you can do so by defining an extension.
Note: I am not endorsing the code below at all; I'm just trying to make it fit the question that you have asked.
public static class LinqExtensions
{
public static ErrorCode BusinessSingle(this IEnumerable<TSource> enumerable, Func<TSource, bool> predicate)
{
TSource result;
try
{
result = enumerable.Single(predicate);
return new NoError(); // ????
}
catch
{
return new ErrorOne();
}
}
}
But it would be far better to do one of the following:
If errors are common, then don't treat it like an Exception but rather a validation rule.
If errors are exceptional, then throw Exception that are differentiated.
You're right that if you're always expecting exactly one element to match your condition, you should use Single() rather than SingleOrDefault().
That means that if that is not the case, your system is a faulted state, and your application should shut down because it is not working correctly. By saying Single(), you're saying "I know there's exactly one there. If there's not, there's something seriously wrong."
By trying to handle the exception and return an error code instead, you're saying something different. You're saying "There should be exactly one there, but if there's not, I can do something else to handle that case." That's what SingleOrDefault() is for.
Because I am writing my first MVVM application and I never write so "big" application. I have no idea how error handling for users is normally done.
I found some "guide":
http://codebuild.blogspot.co.at/2012/01/15-best-practices-about-exception.html
At first point is mentioned: "Don't manage business logic with exceptions. Use conditional statements instead. If a control can be done with if-else statement clearly, don't use exceptions because it reduces readability and performance (e.g. null control, divide by zero control)."
So is better to use if-else statment? Or how do you do? Or is better only working with try-catch statment?
And later when I have more if-else code statments one in other .. is better to use basic error bool and error string for all over the code? When happend just turning this bool to true state and write message to error string? And later by showing result check if any error happend?
If you dont understand the question please ask, or write how do you handle with errors in code for user?
Any general guide will be welcome :)
As mentioned exceptions decrease performance (not sure about readability, I personally never had a problem with that). If you compare how long it takes to check something with IF statement or with TRY-CATCH, you will notice a huge difference in favor of the first one.
I would say use IF statement everywhere, where you can check validity yourself - if it fails, in else statement you can specify what needs to be done (display message to user etc.). For example when dividing x/y
private static void IfMethod()
{
int x = 10;
int y = 0;
if (y != 0)
{
Console.WriteLine(x / y);
}
else
{
Console.WriteLine("y is 0");
}
}
Try-catch is more for situations where you can't predict everything. For example if you are trying to read/write a file you will never for 100% know if you have access to that particular file, the file system or if the file actually exist. This is especially true if you are writing applications for someone else. You have no way to know how they configured their PC, access rights etc.
Hope this helps.
Don't manage business logic with exceptions. Use conditional
statements instead. If a control can be done with if-else statement
clearly, don't use exceptions because it reduces readability and
performance
True. But let's clarify, what is meant here.
This is a sample, when logic is built on exceptions:
private int? Foo(int a)
{
try
{
// bar is some int field
return bar / a;
}
catch (DivideByZeroException)
{
return null;
}
}
Here, method Foo expects, that a can be 0. Hence, a == 0 isn't an exception. But, instead of this:
private int? Foo(int a)
{
if (a == 0)
return null;
return bar / a;
}
the logic of this method uses an exception to detect, that result of the method is undetermined, and returns special value (null).
On the other hand, here's sample, when you must use exception:
public int Foo(int a)
{
if (a == 0)
throw new ArgumentOutOfRangeException("a can't be 0!");
return bar / a;
}
This version of Foo is a public method from class library. The logic of Foo can't handle the case, when a == 0. So, it must check input parameter, and throw exception.
To re-phrase citation above:
do not throw exceptions, if current state can (and must) be handled by your business logic; use conditional statements instead.
do throw exceptions, if current state is unexpected, and cannot (must not) be handled by your business logic.
This is not so much of a problem but more feedback and thoughts. I have been considering an implementation for methods that have been tested thoroughly through our internal teams. I would like to write a generic exception catch method and reporting service.
I relize this is not as easy as a "try-catch" block, but allows for a uniform method for catching exceptions. Ideally I would like to execute a method, provide a failure callback and log all the parameters from the calling method.
Generic Try-Execute.
public class ExceptionHelper
{
public static T TryExecute<T, TArgs>(Func<TArgs, T> Method, Func<TArgs, T> FailureCallBack, TArgs Args)
{
try
{
return Method(Args);
}
catch (Exception ex)
{
StackTrace stackTrace = new StackTrace();
string method = "Unknown Method";
if (stackTrace != null && stackTrace.FrameCount > 0)
{
var methodInfo = stackTrace.GetFrame(1).GetMethod();
if (methodInfo != null)
method = string.Join(".", methodInfo.ReflectedType.Namespace, methodInfo.ReflectedType.Name, methodInfo.Name);
}
List<string> aStr = new List<string>();
foreach (var prop in typeof(TArgs).GetProperties().Where(x => x.CanRead && x.CanWrite))
{
object propVal = null;
try
{
propVal = prop.GetValue(Args, null);
}
catch
{
propVal = string.Empty;
}
aStr.Add(string.Format("{0}:{1}", prop.Name, propVal.ToString()));
}
string failureString = string.Format("The method '{0}' failed. {1}", method, string.Join(", ", aStr));
//TODO: Log To Internal error system
try
{
return FailureCallBack(Args);
}
catch
{
return default(T);
}
}
}
}
What I know as draw backs.
Performance Loss using reflection
MethodBase (methodInfo) may not be available through optimization
The try-catch around the error handler. Basically I could use the TryExecute wrapper for the try-catch around the error call back however that could result in a stack overflow situation.
Here would be a sample implementation
var model = new { ModelA = "A", ModelB = "B" };
return ExceptionHelper.TryExecute((Model) =>
{
throw new Exception("Testing exception handler");
},
(Model) =>
{
return false;
},
model);
Thoughts and comments appreciated.
That's a lot of code to put in a catch, including two more try/catch blocks. Seems like a bit of overkill if you ask me, with a good amount of risk that a further exception can obscure the actual exception and that the error information would be lost.
Also, why return default(T)? Returning defaults or nulls as indications of a problem is usually pretty sloppy. If nothing else, it requires the same conditional to be wrapped around every call to the method to check for the return and respond to... some error that has gone somewhere else now.
Honestly, that usage example looks pretty messy, too. It looks like you'll end up obscuring the actual business logic with the error-trapping code. The entire codebase will look like a series of error traps, with actual business logic hidden somewhere in the entanglement of it. This takes valuable focus off of the actual intent of the application and puts something of background infrastructure importance (logging) at the forefront.
Simplify.
If an exception occurs within a method, you generally have two sensible options:
Catch (and meaningfully handle) the exception within the method.
Let the exception bubble up the stack to be caught elsewhere.
There's absolutely nothing wrong with an exception escaping the scope of the method in which it occurs. Indeed, exceptions are designed to do exactly that, carrying with them useful stack information about what happened and where. (And, if you add meaningful runtime context to the exception, it can also carry information about why.)
In fact, the compiler even subtly hints at this. Take these two methods for example:
public int Sum(int first, int second)
{
// TODO: Implement this method
}
public int Product(int first, int second)
{
throw new NotImplementedException();
}
One of these methods will compile, one of them will not. The compiler error will state that not all code paths return a value on the former method. But why not the latter? Because throwing an exception is a perfectly acceptable exit strategy for a method. It's how the method gives up on what it's doing (the one thing it should be trying to do and nothing more) and let's the calling code deal with the problem.
The code should read in a way that clearly expresses the business concept being modeled. Error handling is an important infrastructure concept, but it's just that... infrastructure. The code should practically scream the business concept being modeled, clearly and succinctly. Infrastructure concerns shouldn't get in the way of that.
This is very rarely going to be useful.
It covers only cases where:
The method has a well-defined means of obtaining an appropriate return value in the face of failure.
You'd actually care to log that it happened.
Now, 2 is very common with exceptions of all sorts, but not where 1 is true too.
1 of course is rare, since in most cases if you could produce a reasonable return value for given parameters by means X you wouldn't be trying means Y first.
It also has a default behaviour of returning default(T) - so null or all zeros - if the fallback doesn't work.
This only works where your case 1 above has "something that just returns null as a result because we don't really care very much what this thing does", or where the called method never returns null, in which case you then test for null, which means that your real error-handling code happens there.
In all, what you've got here is a way in which exceptions that would be trappable by real code have to be caught for by testing (and sometimes testing + guesswork) instead, and those that would bring down a program in a clear place with nice debugging information will instead put it into a state where you don't know what's going on anywhere, but at least of the few dozen bugs that got logged before something managed to bring it down fully, one of the is probably the actual problem
When you've a catch on some exception for a particular reason, by all means log the exception. Note that this is not so much to help find bugs (if that exception being raised there is a bug, you shouldn't be catching it there), but to cancel out the fact that having a catch there could hide bugs - i.e. to cancel out the very effect you are deliberately encouraging by putting catches all over the place. (E.g. you expect a regularly hit webservice to fail to connect on occasion, and you can go on for some hours with cached data - so you catch the failure and go on from cache - here you log because if there was a bug meaning you were never trying to hit the webservice correctly, you've just hidden it).
It's also reasonable to have some non-interactive (service or server) app log all exceptions that reach the top of the stack, because there's nobody there to note the exception.
But exceptions are not the enemy, they're the messenger. Don't shoot the messenger.
I recenly encountered this problem in a project: There's a chain of nested objects, e.g.: class A contains an instance variable of class B, which in turns has an instance variable of class C, ..., until we have a node in the tree of class Z.
----- ----- ----- ----- -----
| A | ---> | B | ---> | C | ---> | D | ---> ... ---> | Z |
----- ----- ----- ----- -----
Each class provides getters and setters for its members. The parent A instance is created by an XML parser, and it is legal for any object in the chain to be null.
Now imagine that at a certain point in the application, we have a reference to an A instance, and only if it contains a Z object, we must invoke a method on it. Using regular checks, we get this code:
A parentObject;
if(parentObject.getB() != null &&
parentObject.getB().getC() != null &&
parentObject.getB().getC().getD() != null &&
parentObject.getB().getC().getD().getE() != null &&
...
parentObject.getB().getC().getD().getE().get...getZ() != null){
parentObject.getB().getC().getD().getE().get...getZ().doSomething();
}
I know that exceptions should not be used for ordinary control flow, but instead of the previous code, I have seen some programmers doing this:
try {
parentObject.getB().getC().getD().getE().get...getZ().doSomething();
} catch (NullPointerException e){}
The problem with this code is that it may be confuse when maintaining it, since it doesn't show clearly which objects are allowed to be null. But on the other hand is much more concise and less "telescopic".
Is it an acceptable to do this to save development time?
How could the API be redesigned to avoid this problem?
The only thing I can think of to avoid the long null checking is to provide void instances of the nested objects and providing isValid methods for each one of them, but wouldn't this create a lot of innecesary objects in memory?
(I've used Java code, but the same question can apply to C# properties)
Thanks.
It is bad design if parentObject needs to know that A contains a B which contains a C wich contains.... That way, everything is coupled to everything. You should have a look at the law of demeter: http://en.wikipedia.org/wiki/Law_Of_Demeter
parentObject should only call methods on its instance variable B. So, B should provide a method that allows for the decision, e.g.
public class A {
private B myB;
//...
public boolean isItValidToDoSomething(){
if(myB!=null){
return myB.isItValidToDoSomething();
}else{
return false;
}
}
}
Eventually, at the level of Z, the method has to return true.
Imho, saving development time is never a reason for tolerating problems in the design. Sooner or later these problems will steal you more time than it would have taken to fix the problems in the first place
It's bad practice to use Exceptions here.
There's a hint in the name: Exceptions are for exceptional circumstances (i.e. unexpected) . If nulls are expected values, then encountering them is not exceptional.
Instead, I'd have a look at the class hierarchy and try to understand why such deep access chaining needs to happen. This seems like a big design issue, you shouldn't normally expect the caller to construct calls using deep knowledge of the structure of objects hidden within class A.
Questions you could ask:
Why does the caller need to doSomething() with the Z object anyway? Why not put the doSomething() on class A? This could propagate doSomething() down the chain if needed and if the relevant field was not null....
What does a null mean if it exists in this chain? The meaning of a null will suggest what business logic should be employed to handle it.... which could be different at each level.
Overall, I suspect the right answer is to put doSomething() on each level of the heirarchy and have the implementation something like:
class A {
...
public void doSomething() {
B b=getB();
if (b!=null) {
b.doSomething();
} else {
// do default action in case of null B value
}
}
}
If you do this, then the API user only has to call a.doSomething(), and you have the added bonus that you can specify different default actions for a null value at each level.
Personally I like to avoid this problem altogether by using an option type. By adjusting the value returned from these methods/properties to be Option<T> rather than T the caller can choose how they wish to handle the case of no value.
An option type can either have a contained value or not (but the option itself can never be null), but the caller cannot simply pass it on without unwrapping the value so it forces the caller to deal with the fact there may be no value.
E.g. in C#:
class A {
Option<B> B { get { return this.optB; } }
}
class B {
Option<C> C { get { return this.optC; } }
}
// and so on
If the caller wants to throw, they merely retrieve the value without explicitly checking to see if there is one:
A a = GetOne();
D d = a.Value.B.Value.C.Value.D.Value; // Value() will throw if there is no value
If the caller wants to just default if any step doesn't have a value, they can perform mapping/binding/projection:
A a = GetOne();
D d = a.Convert(a => a.B) // gives the value or empty Option<B>
.Convert(b => b.C) // gives value or empty Option<C>
.Convert(c => c.D) // gives value or empty Option<D>
.ValueOrDefault(new D("No value")); // get a default if anything was empty
If the caller wants to default at each stage, they can:
A a = GetOne();
D d = a.ValueOrDefault(defaultA)
.B.ValueOrDefault(defaultB)
.C.ValueOrDefault(defaultC)
.D.ValueOrDefault(defaultD);
Option is not currently part of C# but I imagine one day will be. You can get an implementation by referencing the F# libraries or you may be able to find an implementation on the web. If you'd like mine, let me know and I'll send it to you.
Well, it depends on exactly what you're doing in the catch. In the above case, it appears that you want to call doSomething() if it's available, but if it isn't you don't care. In this case I would say that trapping the specific exception you're after is just as acceptable as a verbose check to ensure you won't throw one to begin with. There are many "null-safe" methods and extensions that use try-catch in a very similar manner to what you propose; "ValueOrDefault"-type methods are very powerful wrappers for exactly what's been done with the try-catch, for exactly the reason try-catch was used.
Try/catch is, by definition, a program flow control statement. Therefore, it is expected to be used to "control ordinary program flow"; I think the distinction you are trying to make is that it should not be used to control the "happy path" of normal error-free logic flow. Even then I might disagree; there are methods in the .NET Framework and in third-party libraries that either return the desired result or throw an exception. An "exception" is not an "error" until you cannot continue because of it; if there's something else you can try or some default case the situation can boil down to, it can be considered "normal" to receive an exception. So, catch-handle-continue is a perfectly valid use of try-catch, and many uses of exception throwing in the Framework expect you to handle them robustly.
What you want to avoid is using try/catch as a "goto", by throwing exceptions that aren't really exceptions in order to "jump" to the catch statement once some condition is satisfied. This is definitely a hack, and thus bad programming.
The problem with the "catch an exception" approach is that it seems a bit heavy-handed. The exception stack trace should show you where it failed since your method names make it quite clear where you are in the hierarchy but it is not a good way of going about it. Plus how would you recover from the exception and carry on to a good state of your code?
If you must keep this very deep hierarchy then you could use static instances of each object which defines an "empty" state. The best example I can think of which does this is the C# string class which has a static string.Empty field. Then each call of getB(), getC() ... getZ() would return either a real value or the "empty" state, allowing you to chain the method calls.
By making the "empty" state instances static there would only be one of each type in your system. But you would need to consider what an "empty" state looks like for each type in your hierarchy and make sure it doesn't affect any other part of your application inadvertently.
In Python, they encourage the style of "easier to ask forgiveness than permission", which could be applied here to say that it's better to just optimistically try to get to Z without safety checking, and let the exception handler fix a miss. That's easier to code, and it's more performant if the call of Z not being in the call chain is less likely than the case that it will be.
Aside from violating a bunch of OOP good design principles and exposing deeply nested private members, this code also seems vaguely dynamic in nature. That is, you want to call method X but only if X exists on the object, and you want that logic to apply to all objects in a hierarchy of unknown length. And you can't change the design because this is what your XML translation gives you.
Can you change languages then? Statically-typed C# may not be the best choice for what you're doing here. Maybe using Iron Python or some other language that's a little looser on typing will let you more easily manipulate your DOM. Once you've got the data in a stable state, you can pass that off to C# for the rest.
Using exceptions seem a poor fit here. What if one of the getters contained non-trivial logic, and threw a NullPointerException? Your code would swallow that exception without intending to. On a related note, your code samples exhibit different behaviour if parentObject is null.
Also, there really is no need to "telescope":
public Z findZ(A a) {
if (a == null) return null;
B b = a.getB();
if (b == null) return null;
C c = b.getC();
if (c == null) return null;
D d = c.getD();
if (d == null) return null;
return d.getZ();
}
I think you could provide static isValid methods on each class, for example for class A that would be:
public class A {
...
public static boolean isValid (A obj) {
return obj != null && B.isValid(obj.getB());
}
...
}
And so on. Then you would have:
A parentObject;
if (A.isValid(parentObject)) {
// whatever
}
However, although I won't get into you business I must say that such a method chaining does not say anything good about the design; maybe it's a sign of need for refactoring.
I agree with the other answers that this should not need to be done, but if you must here is an option:
You could create an enumerator method once such as:
public IEnumerable<type> GetSubProperties(ClassA A)
{
yield return A;
yield return A.B;
yield return A.B.C;
...
yield return A.B.C...Z;
}
And then use it like:
var subProperties = GetSubProperties(parentObject);
if(SubProperties.All(p => p != null))
{
SubProperties.Last().DoSomething();
}
The enumerator will be lazily evaluated leading to no exceptions.