Can you use a throw or try-catch within a constructor?
If so, what is the purpose of having a constructor that has an argument that can throw an exception?
This constructor is an example:
public Chat()
{
chatClient = new Client(Configuration.LoginEmail, Configuration.LoginPassword);
chatRoom = chatClient.JoinRoom(Configuration.RoomUrl);
}
The line chatRoom = chatClient.JoinRoom(Configuration.RoomUrl); can throw exceptions.
Throwing an exception when appropriate is part of a constructor's job.
Let's consider why we have constructors at all.
One part is convenience in having a method that sets various properties, and perhaps does some more advanced initialisation work (e.g. a FileStream will actually access the relevant file). But then if it was really that convenient all the time we wouldn't sometimes find member initialisers convenient.
The main reason for constructors is so that we can maintain object invariants.
An object invariant is something we can say about an object at the beginning and end of every method call. (If it was designed for concurrent use we would even have invariants that held during method calls).
One of the invariants of the Uri class is that if IsAbsoluteUri is true, then Host will be string that is a valid host, (if IsAbsoluteUri is false Host might be a valid host if it's scheme-relative, or accessing it might cause an InvalidOperationException).
As such when I'm using an object of such a class and I've checked IsAbsoluteUri I know I can access Host without an exception. I also know that it will indeed be a hostname, rather than e.g. a short treatise on mediaeval and early-modern beliefs in the apotropaic qualities of bezoars.
Okay, so some code putting such a treatise in there isn't exactly likely, but code putting some sort of junk into an object certainly is.
Maintaining an invariant comes down to making sure that the combinations of values the object holds always make sense. That has to be done in any property-setter or method that mutates the object (or by making the object immutable, because you can never have an invalid change if you never have a change) and those that set values initially, which is to say in a constructor.
In a strongly typed language we get some of the checking from that type-safety (a number that must be between 0 and 15 will never be set to "Modern analysis has found that bezoars do indeed neutralise arsenic." because the compiler just won't let you do that.) but what about the rest?
Consider the constructors for List<T> that take arguments. One of them takes an integer, and sets the internal capacity accordingly, and the other an IEnumerable<T> that the list is filled with. The start of these two constructors are:
public List(int capacity)
{
if (capacity < 0) throw new ArgumentOutOfRangeException("capacity", capacity, SR.ArgumentOutOfRange_NeedNonNegNum);
/* … */
public List(IEnumerable<T> collection)
{
if (collection == null)
throw new ArgumentNullException("collection");
So if you call new List<string>(-2) or new List<int>(null) you get an exception, rather than an invalid list.
An interesting thing to note about this case, is that this is a case where they could possibly have "fixed" things for the caller. In this case it would have been safe to consider negative numbers as the same as 0 and null enumerables as the same as an empty one. They decided to throw anyway. Why?
Well, we have three cases to consider when writing constructors (and indeed other methods).
Caller gives us values we can use directly.
Eh, use them.
Caller gives us values we can't meaningfully use at all. (e.g. setting a value from an enum to an undefined value).
Definitely throw an exception.
Caller gives us values we can massage into useful values. (e.g. limiting a number of results to a negative number, which we could consider as the same as zero).
This is the trickier case. We need to consider:
Is the meaning unambiguous? If there's more than one way to consider what it "really" means, then throw an exception.
Is the caller likely to have arrived at this result in a reasonable manner? If the value is just plain stupid, then the caller presumably made a mistake in passing it to the constructor (or method) and you aren't doing them any favours in hiding their mistakes. For one thing, they're quite likely making other mistakes in other calls but this is the case where it becomes obvious.
If in doubt, throw an exception. For one thing if you're in doubt about what you should do then it's likely the caller would be in doubt about what they should expect you to do. For another it's much better to come back later and turn code that throws into code that doesn't than turn code that doesn't throw into code that does, because the latter will be more likely to turn working uses into broken applications.
So far I've only looked at code that can be considered validation; we were asked to do something silly and we refused. Another case is when we were asked to do something reasonable (or silly, but we couldn't detect that) and we weren't able to do it. Consider:
new FileStream(#"D:\logFile.log", FileMode.Open);
There's nothing invalid in this call that should definitely fail. All validation checks should pass. It will hopefully open the file at D:\logFile.log in read mode and give us a FileStream object through which we can access it.
But what if there's no D:\logFile.log? Or no D:\ (amounts to the same thing, but the internal code might fail in a different way) or we don't have permission to open it. Or it's locked by another process?
In all of these cases we're failing to do what is asked. It's no good our returning an object that represents attempts to read a file that are all going to fail! So again, we throw an exception here.
Okay. Now consider the case of StreamReader() that takes a path. It works a bit like (adjusting to cut out some indirection for the sake of example):
public StreamReader(String path, Encoding encoding, bool detectEncodingFromByteOrderMarks, int bufferSize)
{
if (path==null || encoding==null)
throw new ArgumentNullException((path==null ? "path" : "encoding"));
if (path.Length==0)
throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
if (bufferSize <= 0)
throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
Contract.EndContractBlock();
Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.SequentialScan, Path.GetFileName(path), false, false, true);
Init(stream, encoding, detectEncodingFromByteOrderMarks, bufferSize, false);
}
Here we've got both cases where a throw might happen. First we've got validation against bogus arguments. After that we've a call to the FileStream constructor that in turn might throw an exception.
In this case the exception is just allowed to pass through.
Now the cases we need to consider are a tiny bit more complicated.
With most of the validation cases considered at the beginning of this answer, it didn't really matter in what order we did things. With a method or property we have to make sure that we've either changed things to be in a valid state or thrown an exception and left things alone, otherwise we can still end up with the object in an invalid state even if the exception was thrown (for the most part it suffices to do all of your validation before you change anything). With constructors it doesn't much matter what order things are done in, since we're not going to return an object in that case, so if we throw at all, we haven't put any junk into the application.
With the call to new FileStream() above though, there could be side-effects. It's important that it is only attempted after any other case that would throw an exception is done.
For the most part again, this is easy to do in practice. It's natural to put all of your validation checks first, and that's all you need to do 99% of the time. An important case though is if you are obtaining an unmanaged resource in the course of a constructor. If you throw an exception in such a constructor then it will mean the object wasn't constructed. As such it won't be finalised or disposed, and as such the unmanaged resource won't be released.
A few guidelines on avoiding this:
Don't use unmanaged resources directly in the first place. If at all possible, work through managed classes that wrap them, so it's that object's problem.
If you do have to use an unmanaged resource, don't do anything else.
If you need to have a class with both an unmanaged resource and other state, then combine the two guidelines above; create a wrapper class that only deals with the unmanaged resource and use that within your class.
Better yet, use SafeHandle to hold the pointer to the unmanaged resource if at all possible. This deals with a lot of the work for point 2 very well.
Now. What about catching an exception?
We can certainly do so. The question is, what do we do when we've caught something? Remember that we have to either create an object that matches what we were asked for, or throw an exception. Most of the time if one of the things we've attempted in the course of that fails, there isn't anything we can do to successfully construct the object. We're likely therefore to just let the exception pass through, or to catch an exception just to throw a different one more suitable from the perspective of someone calling the constructor.
But certainly if we can meaningfully continue on after a catch then that's allowed.
So in all, the answer to "Can you use a throw or try and catch within a constructor?" is, "Yes".
There is one fly in the ointment. As seen above the great thing about throwing within a constructor is that any new either gets a valid object or else an exception is thrown; there's no in between, you either have that object or you don't.
A static constructor though, is a constructor for the class as a whole. If an instance constructor fails, you don't get an object but if a static constructor fails you don't get a class!
You're pretty much doomed in any future attempt to make use of that class, or any derived from it, for the rest of the life of the application (strictly speaking, for the rest of the life of the app domain). For the most part this means throwing an exception in a static class is a very bad idea. If it's possible that something attempted and failed might be attempted and succeed another time, then it shouldn't be done in a static constructor.
About the only time when you want to throw in a static constructor is when you want the application to totally fail. For example, it's useful to throw in a web application that lacks a vital configuration setting; sure, it's annoying to have every single request fail with the same error message, but that means you're sure to fix that problem!
Can you use a throw or try and catch within a constructor?
Both are possible.
If an exception can happen during construction of an object instance, and there is something you can do about it, catch it and try to fix it.
If there is nothing you can do about the exception, it is generally best to allow it to propagate (rather than leaving the object instance in an improperly initialized state).
The normal lifecycle of an object is interrupted if an exception is thrown in a instance constructor. So if the object has a destructor to clean up any resources then an exception thrown in the constructor will prevent the destructor running and thus forms a memory leak. Always catch, clean up, and re-throw if you have any disposable resources allocated in the constructors or for any fields.
If an exception is thrown in a static constructor then the class is no longer in a state that can be used by the AppDomain. So always catch exceptions in static constructors and deal with them. Do not re-throw and do not leave them uncaught.
Catching and handling exceptions in any constructor is fine to do.
But as per normal, it is 1000x better to code to avoid exceptions rather than let them occur.
See MSDN Constructor Design & Eric Lippert's Vexing Exceptions.
Related
I would like to return exceptions from a method, like this:
Exception f()
{
try
{
// Do something.
return null;
}
catch(Exception e)
{
return e;
}
}
I know that this is considered bad practice, but are there any technical reasons to avoid this?
EDIT: This is not the same question as Is it bad practice to return Exceptions from your methods. I am asking about technical reasons, not best practices.
There are no 'technical' reasons to avoid this. That is, the .Net framework will happily support this type of arrangement.
Also be aware that throwing exceptions incurs a performance penalty, so avoid relying on throwing exceptions for your normal control flow. They should only be used when something has genuinely gone wrong.
It's also fine to instantiate an exception without throwing it:
Exception f()
{
return new Exception("message");
}
Here are some reasons that you may want to rethink that design.
Firstly, new ArgumentOutOfRangeException(...); does not produce your exception stack trace is not generated until you throw it. This may confuse debugging efforts further down the stack. The stack trace will literally be lying.
Secondly, Exception is heavier than some sort of status enum to indicate what type of error occurred. It is hard to see what benefit you are getting out of the response object being of type exception. It presumably requires the caller to subsequently perform a bunch of if (response is FileNotFoundException) .... and decide what they want to do for each.
This means that you lose the ability to differentiate between expected exceptions and unexpected exceptions in a given function. Take a well understood unique constraint violation. Somewhere within your call, or something you call, an insert statement is rejected by the DBMS because of another record having this value. Depending on your use case, this is either an exceptional circumstance indicating something somewhere went very wrong (eg, a corrupt data file), or a result in its own right (eg, a booking system that allocated a seat to someone else between showing you its availability and you accepting). In the first case, you would want your caller to bubble that up to the point in the application which knows what to do about that. In the second, you can safely return that for the caller to do its business.
Thirdly, it is a violation of the principle of least astonishment. Exceptions, by design, are bail out by default. Unless I explicitly catch an exception, it will bail out of my method, excecuting the stuff in my except and finally blocks, nicely calling dispose for me at the end of any using blocks and repeat in my method's caller. What it will never do is execute the code of mine that might be relying on the results of that method call.
Your design here is ignore by default. Unless I explicitly check the result and choose to throw, it will carry on executing my code. Consider this contrived example:
Exception error;
error = GetData(out data);
if (error is DbException) return error;
if (error is ArgumentOutOfRangeException) return error;
// if (error is ....... etc
error = ApplyChangesToData(data);
// if (error is ....... etc
error = SaveData(data);
// if (error is ....... etc
Now the stakes are high if I miss something, because my partially constructed data object may then make its way through the ApplyChangesToData method and then get saved back to the database in corrupted form. This could be as simple as you not anticipating that internally GetData hits a SocketException or an OutOfMemoryException. It isn't just making your abstraction a bit leaky, it means that unless you do have a leaky abstraction, your code cannot be safely written. My code has to know whether you are talking to SqlServer or Oracle or Mongo or whatever so I can anticipate all the possible exceptions you may retun and include them in my if lines. Of course I could put an else in and throw any exception object, but presumably you don't want to do this or you wouldn't be catching it in the first place.
On the other hand, if you were allowing the exceptions to bubble up, and I was confident in what such an exception meant in my context and could still meaningfully carry on, I still have the option of catching that exception and reacting to or suppressing it.
The only exception (pun unintended) that I can think of is at the edge of an API service layer, where you might want to log the exception then return a generic "something went wrong on the server" rather than blab your dirty laundry and expose security sensitive information over a public facing endpoint.
I hope I have convinced you (or , if not, at least someone in the future reading this suggestion) not to go down that dragon-filled path.
Should you set all the objects to null (Nothing in VB.NET) once you have finished with them?
I understand that in .NET it is essential to dispose of any instances of objects that implement the IDisposable interface to release some resources although the object can still be something after it is disposed (hence the isDisposed property in forms), so I assume it can still reside in memory or at least in part?
I also know that when an object goes out of scope it is then marked for collection ready for the next pass of the garbage collector (although this may take time).
So with this in mind will setting it to null speed up the system releasing the memory as it does not have to work out that it is no longer in scope and are they any bad side effects?
MSDN articles never do this in examples and currently I do this as I cannot
see the harm. However I have come across a mixture of opinions so any comments are useful.
Karl is absolutely correct, there is no need to set objects to null after use. If an object implements IDisposable, just make sure you call IDisposable.Dispose() when you're done with that object (wrapped in a try..finally, or, a using() block). But even if you don't remember to call Dispose(), the finaliser method on the object should be calling Dispose() for you.
I thought this was a good treatment:
Digging into IDisposable
and this
Understanding IDisposable
There isn't any point in trying to second guess the GC and its management strategies because it's self tuning and opaque. There was a good discussion about the inner workings with Jeffrey Richter on Dot Net Rocks here: Jeffrey Richter on the Windows Memory Model and
Richters book CLR via C# chapter 20 has a great treatment:
Another reason to avoid setting objects to null when you are done with them is that it can actually keep them alive for longer.
e.g.
void foo()
{
var someType = new SomeType();
someType.DoSomething();
// someType is now eligible for garbage collection
// ... rest of method not using 'someType' ...
}
will allow the object referred by someType to be GC'd after the call to "DoSomething" but
void foo()
{
var someType = new SomeType();
someType.DoSomething();
// someType is NOT eligible for garbage collection yet
// because that variable is used at the end of the method
// ... rest of method not using 'someType' ...
someType = null;
}
may sometimes keep the object alive until the end of the method. The JIT will usually optimized away the assignment to null, so both bits of code end up being the same.
No don't null objects. You can check out https://web.archive.org/web/20160325050833/http://codebetter.com/karlseguin/2008/04/28/foundations-of-programming-pt-7-back-to-basics-memory/ for more information, but setting things to null won't do anything, except dirty your code.
Also:
using(SomeObject object = new SomeObject())
{
// do stuff with the object
}
// the object will be disposed of
In general, there's no need to null objects after use, but in some cases I find it's a good practice.
If an object implements IDisposable and is stored in a field, I think it's good to null it, just to avoid using the disposed object. The bugs of the following sort can be painful:
this.myField.Dispose();
// ... at some later time
this.myField.DoSomething();
It's good to null the field after disposing it, and get a NullPtrEx right at the line where the field is used again. Otherwise, you might run into some cryptic bug down the line (depending on exactly what DoSomething does).
Chances are that your code is not structured tightly enough if you feel the need to null variables.
There are a number of ways to limit the scope of a variable:
As mentioned by Steve Tranby
using(SomeObject object = new SomeObject())
{
// do stuff with the object
}
// the object will be disposed of
Similarly, you can simply use curly brackets:
{
// Declare the variable and use it
SomeObject object = new SomeObject()
}
// The variable is no longer available
I find that using curly brackets without any "heading" to really clean out the code and help make it more understandable.
In general no need to set to null. But suppose you have a Reset functionality in your class.
Then you might do, because you do not want to call dispose twice, since some of the Dispose may not be implemented correctly and throw System.ObjectDisposed exception.
private void Reset()
{
if(_dataset != null)
{
_dataset.Dispose();
_dataset = null;
}
//..More such member variables like oracle connection etc. _oraConnection
}
The only time you should set a variable to null is when the variable does not go out of scope and you no longer need the data associated with it. Otherwise there is no need.
this kind of "there is no need to set objects to null after use" is not entirely accurate. There are times you need to NULL the variable after disposing it.
Yes, you should ALWAYS call .Dispose() or .Close() on anything that has it when you are done. Be it file handles, database connections or disposable objects.
Separate from that is the very practical pattern of LazyLoad.
Say I have and instantiated ObjA of class A. Class A has a public property called PropB of class B.
Internally, PropB uses the private variable of _B and defaults to null. When PropB.Get() is used, it checks to see if _PropB is null and if it is, opens the resources needed to instantiate a B into _PropB. It then returns _PropB.
To my experience, this is a really useful trick.
Where the need to null comes in is if you reset or change A in some way that the contents of _PropB were the child of the previous values of A, you will need to Dispose AND null out _PropB so LazyLoad can reset to fetch the right value IF the code requires it.
If you only do _PropB.Dispose() and shortly after expect the null check for LazyLoad to succeed, it won't be null, and you'll be looking at stale data. In effect, you must null it after Dispose() just to be sure.
I sure wish it were otherwise, but I've got code right now exhibiting this behavior after a Dispose() on a _PropB and outside of the calling function that did the Dispose (and thus almost out of scope), the private prop still isn't null, and the stale data is still there.
Eventually, the disposed property will null out, but that's been non-deterministic from my perspective.
The core reason, as dbkk alludes is that the parent container (ObjA with PropB) is keeping the instance of _PropB in scope, despite the Dispose().
Stephen Cleary explains very well in this post: Should I Set Variables to Null to Assist Garbage Collection?
Says:
The Short Answer, for the Impatient
Yes, if the variable is a static field, or if you are writing an enumerable method (using yield return) or an asynchronous method (using async and await). Otherwise, no.
This means that in regular methods (non-enumerable and non-asynchronous), you do not set local variables, method parameters, or instance fields to null.
(Even if you’re implementing IDisposable.Dispose, you still should not set variables to null).
The important thing that we should consider is Static Fields.
Static fields are always root objects, so they are always considered “alive” by the garbage collector. If a static field references an object that is no longer needed, it should be set to null so that the garbage collector will treat it as eligible for collection.
Setting static fields to null is meaningless if the entire process is shutting down. The entire heap is about to be garbage collected at that point, including all the root objects.
Conclusion:
Static fields; that’s about it. Anything else is a waste of time.
There are some cases where it makes sense to null references. For instance, when you're writing a collection--like a priority queue--and by your contract, you shouldn't be keeping those objects alive for the client after the client has removed them from the queue.
But this sort of thing only matters in long lived collections. If the queue's not going to survive the end of the function it was created in, then it matters a whole lot less.
On a whole, you really shouldn't bother. Let the compiler and GC do their jobs so you can do yours.
Take a look at this article as well: http://www.codeproject.com/KB/cs/idisposable.aspx
For the most part, setting an object to null has no effect. The only time you should be sure to do so is if you are working with a "large object", which is one larger than 84K in size (such as bitmaps).
I believe by design of the GC implementors, you can't speed up GC with nullification. I'm sure they'd prefer you not worry yourself with how/when GC runs -- treat it like this ubiquitous Being protecting and watching over and out for you...(bows head down, raises fist to the sky)...
Personally, I often explicitly set variables to null when I'm done with them as a form of self documentation. I don't declare, use, then set to null later -- I null immediately after they're no longer needed. I'm saying, explicitly, "I'm officially done with you...be gone..."
Is nullifying necessary in a GC'd language? No. Is it helpful for the GC? Maybe yes, maybe no, don't know for certain, by design I really can't control it, and regardless of today's answer with this version or that, future GC implementations could change the answer beyond my control. Plus if/when nulling is optimized out it's little more than a fancy comment if you will.
I figure if it makes my intent clearer to the next poor fool who follows in my footsteps, and if it "might" potentially help GC sometimes, then it's worth it to me. Mostly it makes me feel tidy and clear, and Mongo likes to feel tidy and clear. :)
I look at it like this: Programming languages exist to let people give other people an idea of intent and a compiler a job request of what to do -- the compiler converts that request into a different language (sometimes several) for a CPU -- the CPU(s) could give a hoot what language you used, your tab settings, comments, stylistic emphases, variable names, etc. -- a CPU's all about the bit stream that tells it what registers and opcodes and memory locations to twiddle. Many things written in code don't convert into what's consumed by the CPU in the sequence we specified. Our C, C++, C#, Lisp, Babel, assembler or whatever is theory rather than reality, written as a statement of work. What you see is not what you get, yes, even in assembler language.
I do understand the mindset of "unnecessary things" (like blank lines) "are nothing but noise and clutter up code." That was me earlier in my career; I totally get that. At this juncture I lean toward that which makes code clearer. It's not like I'm adding even 50 lines of "noise" to my programs -- it's a few lines here or there.
There are exceptions to any rule. In scenarios with volatile memory, static memory, race conditions, singletons, usage of "stale" data and all that kind of rot, that's different: you NEED to manage your own memory, locking and nullifying as apropos because the memory is not part of the GC'd Universe -- hopefully everyone understands that. The rest of the time with GC'd languages it's a matter of style rather than necessity or a guaranteed performance boost.
At the end of the day make sure you understand what is eligible for GC and what's not; lock, dispose, and nullify appropriately; wax on, wax off; breathe in, breathe out; and for everything else I say: If it feels good, do it. Your mileage may vary...as it should...
I think setting something back to null is messy. Imagine a scenario where the item being set to now is exposed say via property. Now is somehow some piece of code accidentally uses this property after the item is disposed you will get a null reference exception which requires some investigation to figure out exactly what is going on.
I believe framework disposables will allows throw ObjectDisposedException which is more meaningful. Not setting these back to null would be better then for that reason.
Some object suppose the .dispose() method which forces the resource to be removed from memory.
Consider the following issue
When designing a framework, an interface exposing some event is presented
interface I
{
event MyEventHandler MyEvent
}
This interface will eventually be implemented by many different 3rd party vendors, and may be consumed by various clients.
Since each vendor may new up the event args with invalid data, the only control I have as a framework author is at the event args level, so I thought of the following pattern:
class MyEventArgs
{
public int? MyProperty{get;}
MyEventArgs(int arg)
{
if(arg.IsInvalidArgument())//Let's pretend that there's such an extension method
throw new ArgumentException(...)
MyProperty = arg;
}
This ensures that a client can not use invalid values provided by some rogue piece of code, since the constructor throws an exception, hence the integer will have no value assigned, making it a null reference.
However, this also creates overhead in client code, since now the client has to check the HasValue and then access Value, making the EventArgument less user friendly.. This becomes even more cumbersome when the amount of parameters per event argument grow.
I could technically remove the question mark, which would rid the client of the Nullable nonsense, since in my opinion there is no way on god's green earth to obtain a reference to such an instance, but the problem is that this scenario, although easy to test, may have edge cases which I never thought of, hence my question.
Is there any possible way to obtain a reference to an instance whose constructor had thrown an exception and pass it to the event listeners?
When a constructor throws an exception there is no way to obtain a reference to that object (except if the object cooperates by handing out this before throwing; not likely, bad design).
For that reason your invalidly valued object is unreachable. It's state is indeed invalid (default initialized) but nobody can see it. It's like a virtual machine that is corrupted on the inside and tries to launch missiles but you have disabled the virtual NIC.
This pattern is used all over the place. You have used it many times without realizing. For example, if you say new FileStream(null) how would you obtain a reference to that invalid stream? You can't.
Just do the normal thing. It's good that you thought this through, though.
Is there any possible way to obtain a reference to an instance whose constructor had thrown an exception and pass it to the event listeners?
No. But here's an example where it's possible:
class C {
public static C Instance;
public C() {
Instance = this; //publish/leak
throw ...;
}
}
Just don't do that. This is unnatural code anyway. The constructor of an object normally should not do much, it should bring the object into a valid state and not cause side-effects. Side-effects are the only way to publish a reference to this.
There's one more catch: A finalizer will be invoked on that object if one is present. Finalizers are rare because because most of the time unmanaged resources should be held by handle classes. For that reason this issue rarely comes into effect. But a finalizer can see the private state of its object. Make sure that it can deal with that. FileStreams finalizer will probably check for aborted initialization and do nothing.
the client has to check the HasValue and then access Value
Well it's not necessary to make the property a Nullable<int>, as you can only set it from the constructor (assuming an omitted private set), where it is non-nullable.
Is there any possible way to obtain a reference to an instance whose constructor had thrown an exception
No, when a constructor throws an exception, you don't get an instance back.
To answer your question. No. you can't have a null result if an error is encountered in a constructor
However I think the best possible way around this is to add a static constructing function to the MyEventArgs class
public static int DEFAULT_ARG = 1;//you can set this to whatever you want
public static Create(int arg)
{
if(checkArg(arg))
{
return new MyEventArgs(arg);
}
return new MyEventArgs(MyEventArgs.DEFAULT_ARG);
}
Then instead of using the constructor directory using var event = new MyEventArgs(arg); you use var event = MyEventArgs.Create(arg);
It's a bit of a stress using this method on multiple eventargs but hey :) you could always derive all of them from the same generic abstract class
Hope this helps :)
I'm trying to find an answer on that question, which is:
Is the following code is a good practice?
Should I try to reproduce it wherever it's possible or not? and if not, why?
public class ExceptionHelper
{
private static readonly HttpException _errorReadingRequest = new HttpException(500, "Error reading request. Buffer is empty.");
public static Exception ErrorReadingRequest { get { return _errorReadingRequest; } }
}
public class ExceptionThrower
{
public static void ThrowCached1()
{
throw ExceptionHelper.ErrorReadingRequest;
}
// ...
}
I've tried to throw in several places the cached instances and it seems to preserve the stack trace, from MSDN,
The stack trace begins at the statement where the exception is thrown
and ends at the catch statement that catches the exception. Be aware
of this fact when deciding where to place a throw statement.
I understand that as "It stores the stack trace at the throw, not at the creation". However, I'm wondering if there could be a problem when multiple threads try to throw the same cached instance of exception.
On the same MDSN page, they are using an helper function and it seems in the framework, they are doing the same: helper function which recreates the exception and throw.
Note: I know it's not a common case because most of the time, you want a specific message to be stored in the exception so it's easier to understand what's happening.
Maybe the question is just is throw keyword thread safe or not?
Context:
I've stumble upon this kind of code, while code reviewing some performance touchy application code. The goal is to create the maximum of instance during startup and then never (or almost never) instances during execution, in order to limit the GC performance impact (especially because of heap fragmentation occuring with GCHandle thing). I had a bad feeling about this code but needed facts to support my refactoring.
Generally it makes no sense to have one cached exception. CREATING an object is fast. Exceptions shoudl be rare - and catching them has some overhead, as has throwing them. THere is simply nothing gained from having "one exception to rule them all", except:
Threading issues
More convoluted code
Totally ignoring coding standards I have seen in the last 20 years.
If any of those things are your goal - go along.
Maybe the question is just is throw keyword thread safe or not ?
The throw keyword is thread safe - you can have multiple threads throwing at the same time. Using the same exception though is going to get you into trouble, but it is not because the throw KEYWORD is not thread safe but because you maliciously violate thread safety by passing in the same data object.
Throwing an exception mutates that exception object. It stores the stack for example. This is a problem if you want to use the stack trace for logging purposes. You'll get randomly corrupted stacks.
Also, creating an exception object is cheap. This does not accomplish much.
#TomTom gave a great answer, I want just to point out the example for exception caching being a standard practice: TPL's Task class Exception property.
Sometimes, if the exception is thrown inside some asynchronous operation, it is a good practice to save the information about it for the moment you need the result of operation.
But! As TPL's programmers did, you should wrap the original exception inside the new one (for example, AggregateException) so you can see the original source and stacktrace of it.
As for the GC collection's performance hit, you can use other techniques. For example, if there are a lot of objects being created and after that being collected, try to use the structs for DTO-objects instead of classes. If they will fit into a stack size, they will be collected automatically after the method ends it's execution.
If a class implements an interface, how should it handle the situations where eitherIn the execution of a method or property, an internal error occurs which is of a type which a caller might reasonably be expecting to handle, but which a caller perhaps should not. For example, IDictionary.Add does something internally which yields an ArgumentException under circumstances which would imply that the dictionary is corrupt, but would not imply anything bad about the rest of the system? Or they imply that something is corrupted beyond the dictionary? A caller may be expecting to catch and handle the fact that a duplicate key exists in the dictionary, since in some cases the exception may be Vexing (e.g. the same code may be used for a Dictionary that's not accessed by other threads and for a ConcurrentDictionary which is, and the semantics would be workable if an attempt to add a duplicate record caused a clean failure). Letting an ArgumentException percolate would lead a caller to believe that the dictionary is in the same state as if the add never occurred, which could be dangerous, but throwing some other exception type would seem confusing.
In the execution of a method or property, an exception occurs which the caller maybe should or shouldn't handle, and the definition of the interface doesn't provide any hint that any even-remotely-related exception might occur. For example, suppose something goes wrong in the evaluation of IEnumerator, either implying (1) the enumerator got corrupted (possibly by unexpected action on another thread) but retrying the enumeration might succeed; (2) the enumerable object itself is probably corrupted or unusable, but everything else in the system is probably okay (e.g. a lazily-evaluated file parsing routine hit an invalid record); (3) something beyond the enumerable object has been corrupted. IEnumerable only has one defined exception it can throw, but a caller may want to vary its action based upon the 'severity' of the exception.
If I had my druthers, the system would define some types like RetryableFailureException, CleanFailureException, ObjectCorruptFailureException, and most interfaces would be allowed to throw those or derivatives thereof. Since that's not the case, how should one properly handle interfaces, either from the view of the interface or the caller?
BTW, one pattern I've not seen implemented, but would seem useful, would be for methods to accept a delegate parameter to be executed in case the method fails in a way that would cause a "try" method to return false. Such a delegate, supplied by the caller, could then not only throw an exception which the recipient would know to look for, but could also set a flag that was otherwise available only to the caller. The caller could thus know that the exception being caught was indeed the one expected.
An Interface's job is to define the members (and their signatures) that a class must have, not how they should be implemented. Therefore I would say let the exception bubble up the stack. If you really want to define the contract and control some of the implementation (such as error handling) then you should make a base class (I would lean towards a MustInherit/Abstract class in this situation) with MustOverride Methods that the base class calls from its methods (in your situation in a Try Catch so you can do your special error handling).