Does throwing exception at the end of constructor damage the object? - c#

I'm working on a software communicating with external device. The device requires a set of initialization values (calibrationData). Those calibration data differ from piece to piece of this equipment. In first versions the calibrationData can be selected by user and thus the user may by accident load calibrationData obtained on different piece. The device would work, but will measure incorrectly.
I have
public Instrument(CalibrationData calibration)
{
_camera = new Camera();
_driver = new Driver();
if (_camera.GetUniqueId() != calibration.GetCameraUniqueId())
throw new WrongCalibrationException("Calibration file was obtained on different equipment.");
//Don't write anything here. Exception has to be the last code in the constructor.
}
and then somewhere else
try
{
instrument = new Instrument(calibration);
}
catch (WrongCalibrationException e)
{
MessageBox.Show("You tried to load calibration obtained on different device.");
}
I'm not able to check the ID before I'm connected to the device.
This question comprises out of two in fact.
Is my solution correct? I want to test usage of proper calibration automatically and not rely on the programmer using use my code to call another method (Something like Instrument.AreYouProperlyCalibrated())
Is the object constructed properly when the exception is thrown at the end of constructor? I'm a bit afraid that C# is doing some mumbo jumbo after the construcor finishes and that this might be different in case the ctor threw an exception.
Thanks

The instance already fully exists before the constructor begins (indeed, you can even completely bypass all constructors and still get a valid instance) - it just means that any initialization code that didn't execute won't have executed.
For example, while it isn't a good idea, you can pass the object instance out of the type during the constructor, i.e.
_camera.HereIsMe(this);
or
SomeExternalObject.Track(this);
so nothing too terrible will happen, since as far as the runtime is concerned this object exists like normal, and must be handled properly. However, in some cases it is cleaner to use a factory:
public static YourType Create(args) {
// TODO: perform enough work to validate
return new YourType(validated args);
}
But to reiterate; if there is a problem, then throwing from the constructor is not unexpected and is not harmful.

It's a matter of preference. For example, DateTime throws an exception in its constructor. If you'd rather not, you could use a static method like Build(Calibration calibration). A good practice is to use XML comments to let users of your type know that the constructor throws an exception in an <exception> tag.

You can throw exceptions from wherever you want in your code.
If your constructor has a throw somewhere, and that throw occurs, the object won't be created or, to be more correct, it will be created but your code execution flow will follow the exception, so you won't be in the code branch where the object was being created, so it's like it was not created at all for what concerns you.
So I'd say your approach, considering only the code you posted, is ok. Obviously there could be other problems related to things that could be in the Camera and Driver constructors (stuff not disposed, etc) but that's another matter.

it's a contentious subject, but at the end of the day it is perfectly valid to throw exceptions in constructors. here are some links that discuss and validate the practice:
Throwing ArgumentNullException in constructor?
http://bytes.com/topic/c-sharp/answers/518251-throwing-exception-constructor
http://blog.aggregatedintelligence.com/2009/04/can-constructors-throw-exceptions.html

I would like to add to Marc's answer by pointing out that the Camera and Driver objects should be getting injected into the class. See this (one of MANY) article(s) on implementing Dependency Injection in C#
Hopefully I won't get flogged for this being an opinion. ;)

Related

try-catch instead of if in edge cases

Would it be a good idea to replace the if statements with try-catch in the following usecases (performance and readability wise?):
Example 1
public static void AddInitializable(GameObject initializable)
{
if(!HasInstance)
{ // this should only happen if I have forgotten to instantiate the GameManager manually
Debug.LogWarning("GameManager not found.");
return;
}
instance.initializables.Add(initializable);
initializable.SetActive(false);
}
public static void AddInitializable2(GameObject initializable)
{
try
{
instance.initializables.Add(initializable);
initializable.SetActive(false);
}
catch
{
Debug.LogWarning("GameManager not found.");
}
}
Example 2
public static void Init(int v)
{
if(!HasInstance)
{// this should happen only once
instance = this;
}
instance.alj = v;
}
public static void Init2(int v)
{
try
{
instance.alj = v;
}
catch
{
instance = this;
Init(v);
}
}
Edit:
Question 2: How many Exceptions can I get to be still performance positive?
It depends.
Try-blocks are generally cheap, so when the exception is not thrown, that would be an acceptable solution. But: In your case, if the condition is not satisfied (meaning the thing was not initialized before that method was called), this is a programming error, not something that should ever happen in the finished program. It is perfectly valid that such errors crash the program. Makes spotting the bugs and fixing them much easier in development, and avoids that you silently hide it (in example 1, you silently don't do anything, which might cause confusing behavior later).
So: If it would be a programming error, don't use an exception handler, nor a test (except maybe an Assert). Just let the program crash (with a NullReferenceException in this case).
I would agree with PMF: Depends!
On your specific use case and in specific whether something is your fault or something you can't control / predict.
So in general I'd say there are three ways of how to handle stuff that isn't behaving as expected
A) let throw an exception to indicate that this is really bad and there is no way to recover => and most probably crash your app
This usually makes totally sense on development time because while debugging you explicitly want your app to crash so you can find and fix the issue.
This should be happening for everything where the cause is basically something that you messed up and can be fixed by you. (In your case instance not initialized correctly)
B) return something e.g. false to indicate that something went bad but allow this to be handled by the code and e.g. try something else.
In my eyes this should be the preferred way of dealing with stuff you can't control yourself like e.g. user input and other unpredictable conditions like internet connectivity etc.
C) Just ignore it and do nothing at all.
Depends of course on what exactly you are doing but this should actually happen almost never. For a User this can be extremely frustrating and also for you as developer it makes debugging hard to impossible!
In combination with B of course this is valid since something else will already have delt with the issue.
And to add just in general unless you work on some core / reused library I would actually never throw exceptions myself except you are re-throwing caught ones to add additional debugging information. This basically falls under "you can't control" how others will use your library -> this basically from your perspective falls under user input ;)
Now all three options can be achieved by try - catch or if checks internally of course and it depends on your specific case which way you want to go.
Some thoughts of mine on this
Readability wise I would prefer the if already alone because it makes clear exactly which condition is checked. When I see a try - catch I don't know exactly at which point which exact exception might be thrown on first glance.
Thus using try - catch as a replacement for if just obscures what exactly is failing and makes debugging hard to impossible
Exceptions are quite expensive! So performance wise I would say use if wherever possible.
There are cases though - and in my opinion these are the only ones where try - catch would be allowed - where you use a library and there simply is no way to prevent an exception.
Example: FileIO
the file you want to access does not exist
-> You don't need try - catch for this (in my eyes it would be the lazy way). This is something you can and should actually check first if(!File.Exists(...)) so your program can correctly deal with it and handle that case (e.g. you might want to tell the user instead of simply crash or doing nothing).
The file is currently opened by another program so you can't write to it.
-> There is no way to find this out beforehand. You will get an exception and can't avoid it. Here you want to try - catch in order to still allow your code to deal with such case (as before e.g. tell the user instead of simply crash).
But then how you actually deal with them again depends:
If you e.g. use some hardcoded paths and these files definitely should be there -> Exception because it means you as developer messed something up.
If the path comes from user input -> Catch because this is something you as developer can't control but don't just want your app to crash, rather show a hint to the user that he messed it up.
Now in your use case the Example 1 both of your solutions seem pretty bad to me. You go with the last option C and just ignore the call - a user won't see the warning and also a developer might just not note / ignore it.
You definitely want to get an Exception here if this means that your app will not behave correctly and not catch it at all!
In general there is no need for a special bool flag. I would rather go with
if(instance == null)
{
Debug.LogError(...);
return;
}
Because this is most probably a more severe error not only a warning so it at least gains visibility.
In your Example 2 you actually have kind of a lazy initialization anyway so either way the call itself is basically valid.
In such case though again this is something you can easily check and I would not wait for an exception (especially not simply any) because I already know that there definitely will be one at least once.
In my opinion this should rather be
if(instance == null)
{
// I have put `???` because, well, in a "static" method there is no "this" so
// I wonder where the instance should come from in that case ;)
instance = ???;
}
instance.alj = v;
So you're kind of along the right lines here.
Unless you are in dire need of increasing performance, don't try to optimize, and if you do need to optimize, make sure you're doing it right (exceptions are more expensive that if statements, especially if you know they're going to happen)
The first example you've given, I can kind of get behind. You're making the assumption that something was initialized, and if it turns out it wasn't, throw an error. You're logging it, it's ok, you initialize it and you'll probably never have to worry about that exception again.
The second example you've given is a big no no. You should not use exceptions to fall into other logic in your application. Instead, in the Init() method, just always have the line 'instance = this', don't do the if statement. Once you know it's initialized, there should never be a reason for it to throw an exception when used.
Of course, don't go crazy with this, exceptions should only be used for exceptional circumstances. If you write your code and are thinking 'Hmm, so it could be either A scenario or B scenario, and in B scenario I want this to happen, so I'll throw an exception' that's completely the wrong line of thinking. Instead it should be 'Hmm, so all this will happen, but just in case something breaks, I'll put it in a try catch and log it, as who knows, I'm not infallible'
You can see how I've applied the above logic to your two examples,
To my point of view, this is not a good idea.
We usually use try catch when we know what kind of exceptions will appear in the context, and hence a catch without exception type is not a good practice. Moreover, try catch is not expensive only if the exception rarely happens.
In your scenario, since you already know the only problem is that the property HasInstance may be false, you could directly check it with if statement. Using try catch seems more like a cost here, although it works. This seems like you are expecting an error, and you just ignore that error because its message does not matter.
Besides, I see you are using Unity and are creating a singleton GameManager, and actually I think the singleton pattern here might not be quite correct.
For example, if you use the code like this, actually there is virtually no possibility it does not have an instance if you treat your scene and gameobjects properly :)
Exceptions are there when an "impossible" state occurs in your interfaces (Not the keyword - just the word), if you have to try - catch inside your business logic, your design is compromised.
In this case, you would likely gain both extendability, and readability, if you implement the slightly miss-named null-object pattern. (Should be called default object pattern)
And simply never be able to pass a null'ed interface to the method.
So:
public interface IGameObject {
void Activate(instance initializable);
}
public class GameObjectDefault : IGameObject {
public void Activate(instance initializable){
--Does nothing on purpose
}
}
public class GameObjectReal : IGameObject {
private Instance _instance;
public GameObjectReal(Instance instance)
{
_instance = instance;
}
public void Activate(IGameObject initializable) {
_instance.initializables.Add(initializable);
--Do whatever you need to do to the object
}
}
This is pseudo, because I can't see your whole system.
But this way, if you initialize all game objects as DefaultGameObjects, your activate or any other method, will just do nothing.
Now, there is no reason to check for null.
And no reason to do a try catch. Your impossible state, is now, literally, impossible.

Appropriate Exception to throw if you've manually detected a threading error

Suppose I write some multi-threaded C# code. (I know ... bad idea from the get-go ;) )
I have some code B, which I expect to only get called after code A has completed. I write and review my code carefully to convince myself that this is true, but I can't actually enforce that expectation, I can only check whether it is true.
So I put the checks in, and if the check ever fails, I want to throw and exception so that the developer gets a big shouty log message saying "Nope, ya fucked up; there's still an edge case where the threading doesn't do what you'd convinced yourself it did."
What's the best C# Exception type to throw here?
My instinct is to go with that old stand-by InvalidOperationException or possibly just a raw new Exception(message). But it would be nice if there were a slightly more specific type I could throw (like throwing an ArgumentException when that's the issue that's happened)
There are a few Exception types that auto-complete from Thread or Sync but they all look like they're intended for much deeper problems. i.e. there's something wrong with the actual threads. Here the thread are all fine ... it's the developer's threading logic that's in error.
Are there any sensible pre-existing Exception classes to use here?
An InvalidOperationException is the most suitable built in exception for this situation.
See it's official documentation remarks section:
InvalidOperationException is used in cases when the failure to invoke a method is caused by reasons other than invalid arguments. Typically, it is thrown when the state of an object cannot support the method call.
(emphasis mine).
Of course, there's nothing stopping you from creating your own Exception class if you want something more specific, but that would only make sense if you want the exception to carry information that doesn't fit inside the InvalidOperationException (and of course, if you do choose to create your own exception class, be sure to follow the guidlines in How to create user-defined exceptions:
Derive from an existing Exception class
use the word Exception as a suffix to the class name (MyVeryOwnSpecialException)
Implement at least three public constructors:
3.a: A constructor with no parameters
3.b: A constructor that takes in a string message
3.c: A constructor that takes in a string message and an Exception inner exception.

What type of Exception should I throw when an unknown value is passed into a switch statement

Edit 1
Updated to make the enum not an argument to the method...
Question
This type of problem comes up a lot with enums in switch statements. In the example code, the developer has accounted for all countries the program is currently using, but if another country is added to the Country enum, an exception should be thrown. My question is, what type of exception should be thrown?
Example Code:
enum Country
{
UnitedStates, Mexico,
}
public string GetCallingCode(Guid countryId){
var country = GetCountry(countryId);
switch (country)
{
case Country.UnitedStates:
return "1";
break;
case Country.Mexico:
return "52";
break;
default:
// What to throw here
break;
}
}
I've looked at
NotImplemented, The exception that is thrown when a requested method or operation is not implemented.
NotSupported There are methods that are not supported in the base class, with the expectation that these methods will be implemented in the derived classes instead. The derived class might implement only a subset of the methods from the base class, and throw NotSupportedException for the unsupported methods.
For scenarios where it is sometimes possible for the object to perform the requested operation, and the object state determines whether the operation can be performed, see InvalidOperationException.
InvalidOperation is used in cases when the failure to invoke a method is caused by reasons other than invalid arguments.
My guess is either NotImplemented or Invalid Operation. Which one should I use? Does someone have a better option (I know rolling your own is always an option)
I would go with ArgumentException, as the agrument is invalid.
EDIT: http://msdn.microsoft.com/en-us/library/system.argumentexception%28v=vs.71%29.aspx
There is also InvalidEnumArgumentException, which might more accurately describe the problem, however, I have not seen anyone use it before.
One option is to do almost a method contracts check in Debug mode. Throw in an extension method for nice looking form:
[Conditional("DEBUG")]
public static bool AssertIsValid(this System.Enum value)
{
if (!System.Enum.IsDefined(value.GetType(), value))
throw new EnumerationValueNotSupportedException(value.GetType(), value); //custom exception
}
I figured maybe only have it in debug mode so it passes your development/test environment and unit tests and in production there's no overhead (though that's up to you)
public string GetCallingCode(Guid countryId)
{
var country = GetCountry(countryId);
country.AssertIsValid(); //throws if the country is not defined
switch (country)
{
case Country.UnitedStates:
return "1";
case Country.Mexico:
return "52";
}
}
I would suggest though that this is actually the responsibility of your GetCountry method. It should recognize that the countryId is not valid and throw an exception.
Regardless, this should really be caught by your unit tests too or somehow better handled. Wherever you convert a string/int into your enum should be handled by a singular method which in turn can check/throw (just as any Parse method should) and have a unit test that checks all valid numbers.
In general, I don't think the various ArgumentExceptions (and the like) are a good candidate because there are several conditions (non-argument) cases. I think if you move the checking code to a single spot, you may as well throw your own exception that accurately communicates to any developer listening.
EDIT: Considering the discussion, I think there are two particular cases here.
Case 1: Converting underlying type to an equivalent enum
If your methods take some sort of input data (string, int, Guid?), your code performing the conversion into the enum should validate that you have an actual enum that's usable. This is the case I posted above in my answer. In such cases, likely throwing your own exception or possibly InvalidEnumArgumentException.
This should be treated pretty much like any standard input validation. Somewhere in your system you are providing garbage-in so handle it as you would any other parsing mechanism.
var country = GetCountry(countryId);
switch (country)
{
case Country.UnitedStates:
return "1";
case Country.Mexico:
return "52";
}
private Country GetCountry(Guid countryId)
{
//get country by ID
if (couldNotFindCountry)
throw new EnumerationValueNotSupportedException(.... // or InvalidEnumArgumentException
return parsedCountry;
}
EDIT: of course, the compiler requires that your method throws/returns, so not so sure what you should do here. I guess that's up to you. If that actually happens, it probably is a bone-headed exception (case 2 below) since you passed your input validation yet did not update the switch/case to handle the new value, so maybe it should throw new BoneheadedException();
Case 2: Adding a new enumeration value which is not handled by your switch/case blocks in your code
If you are the owner of your code, this falls under the "Boneheaded" exceptions described by Eric Lippert in #NominSim's answer. Though this can actually not result in an exception at all while leaving the program in an exceptional/invalid state.
The best for this is likely any place where you perform switch/case (or of the like) runs against the enumeration, you should consider writing a unit test that automatically runs the method against all defined values of your enumeration. So if you are lazy or accidentally missed a block, your unit tests will warn you that you did not update a method to account for the change in your enumeration listing.
Finally, if your enum is coming from a 3rd party which you did not realize they updated the values, you should write a quick unit test that validates all your expected values. So if you wrote your program with checks for UnitedStates and Mexico, your unit test should just be a switch/case block for those values and throw an exception otherwise warning you when/if they end up adding Canada. When that test fails after updating the 3rd party library, you know what/where you have to make changes to be compatible.
So in this "Case 2", you should throw any old exception you want since it will be handled by your unit tests just so long as it accurately communicates to you or consumers of your unit tests just what exactly is missing.
In either case, I don't think the switch/case code should be caring too much about invalid input and not throwing exceptions there. They should either be thrown at design time (via unit tests) or thrown when validating/parsing input (and therefore throw appropriate "parsing/validation" exceptions)
EDIT: I stumbled upon a post from Eric Lippert discussing how the C# compiler detects if a method with a return value ever hits its "end point" without returning. The compiler is good at guaranteeing that the end point is unreachable sometimes, but in cases as yours above, we developers know it's unreachable (except in the circumstances noted above where BoneheadedExceptions come into play).
What wasn't discussed (at least that I saw) what you should do as a developer to resolve these cases. The compiler requires that you provide a return value or throw an exception even if you know it will never reach that code. Googling hasn't magically surfaced some exception to leverage in this case (though I couldn't figure out good search terms), and I'd rather throw an exception and be informed that my assumption that it cannot reach the end is incorrect rather than returning some value which may not inform me of the problem or result in unwanted behaviour. Maybe some UnexpectedCodePathFailedToReturnValueException of some sort would be most valid in this case. When I have some time, I'll do some more digging and maybe post a question on programmers to garner some discussion.
Of the exceptions you've listed, only InvalidOperationException fits your scenario. I would consider using either this, or either ArgumentException or the more specific ArgumentOutOfRangeException since your switch value is provided as an argument.
Or, as you say, roll your own.
EDIT: Based on your updated question, I would suggest InvalidOperationException if you want to use a framework exception. However, for this more generic case, I would definitely prefer to roll my own - you can't guarantee that InvalidOperationException won't be caught elsewhere in the callstack (possibly by the framework itself!), so using your own exception type is much more robust.
I would use InvalidOperationException if the value you're working with is a product purely of your object's current state. As it says:
The exception that is thrown when a method call is invalid for the object's current state.
Even with your updated question, since the particular value you cannot deal properly with was derived from an argument passed to it, I would still use an ArgumentException - you can explain in the error message that information you're derived from the argument doesn't match anything you can deal with.
For both NotImplementedException and NotSupportedException the expectation is that, no matter what the caller does, they're not going to be able to remedy the situation. Whereas ArgumentException and InvalidOperationException are clues that, if the caller would use a different argument, or transition the object to another state (respectively), the call might work.
Personally, I don't think this is the proper place for any Exception at all. If you add a Country, you should add a case to the switch statement. The code shouldn't break because you add a value to an enum.
There is an article on when to use exceptions by Eric Lippert, that categorizes the type of exception you are looking for as: (forgive the wording it is not mine)
Boneheaded exceptions are your own darn fault, you could have prevented them and therefore they are bugs in your code. You should not catch them; doing so is hiding a bug in your code. Rather, you should write your code so that the exception cannot possibly happen in the first place, and therefore does not need to be caught.
it's impossible to pass another value, because your enum limits the possible values to the one you handle. so you don't need any exception.

What type of exception to throw in this case?

I'm writing a c# application which uses automation to control another program. Naturally that program must be running for my program to work. When my program looks for the application and can't find it I'd like to throw an exception (for now later of course I could try opening the application, or telling the user to open it, or ...).
Should I implement a custom exception - or use the existing NotSupportedException (or one of the other .NET exceptions). If a custom exception, what would you suggest? I was thinking of implementing a custom exception I'd call it MyAppNameException and then just use the message to declare what the problem was?
Are there any general rules to throwing exceptions in a way that makes your program more readable and user friendly, or am I just giving this too much thought :)?
Thanks!
First, define MyAppCustomException as an abstract base class.
Then inherit from it with AppNotFoundCustomException.
This way you can catch all exceptions from your app, or just specific ones.
Here's some example code that illustrates the concept:
public abstract class MyAppCustomException : System.Exception
{
internal MyAppCustomException(string message)
: base(message)
{
}
internal MyAppCustomException(string message, System.Exception innerException)
: base(message,innerException)
{
}
}
public class AppNotFoundCustomException : MyAppCustomException
{
public AppNotFoundCustomException(): base("Could not find app")
{
}
}
And here's a client try/catch example:
try
{
// Do Stuff
}
catch(AppNotFoundCustomException)
{
// We know how to handle this
}
catch(MyAppCustomException) // base class
{
// we don't know how to handle this, but we know it's a problem with our app
}
The Framework Guidelines book that I use indicates that you should only create a custom exception when the error condition can be programmatically handled in a different way than any existing exceptions.
In your case, if you wanted to create a custom exception in order to launch a back-end installation program, that is unique and I think a custom exception would be okay.
Otherwise, something from the System.Runtime.InteropServices.ExternalException heirarchy may be appropriate.
Yeah, you're overdoing it. Nothing good is going to happen when you throw an exception, any exception, that program isn't magically going to start running when you do. Only bad things might happen, like some code actually catching that exception and trying to continue. Or nobody catching it and getting a Windows Error Report dialog. Might as well put up a message box and call it a day with Environment.Exit().
Of course, it could be more useful to the user if you actually start that program if you find it isn't running.
You certainly shouldn't use NotSupportedException, as you suggest, because your application does support the method in question. NotSupportedException is used when a interface or abstract class is implemented, but with some members not fully implemented as they don't make sense in the context (reading from an output stream, clearing a readonly collection, etc).
A closer match is something InvalidOperationException, where a member can be used, but not given the current state.
You say "application", which suggests an executable rather than a component for use by something else. In this case you aren't going to bubble the exception up to the calling code (since there isn't calling code) but either raise a dialog (for a GUI app) or write to Console.Error (for a console app). This makes it likely that either you're just going to display the value of the Message property of the exception, or that you just need the class type to flag a particular message. Either simply deriving AppNotRunningException from Exception or just using Exception directly will probably serve perfectly well, depending on which of the two you find most convenient.

Is this good C# style?

Consider the following method signature:
public static bool TryGetPolls(out List<Poll> polls, out string errorMessage)
This method performs the following:
accesses the database to generate a list of Poll objects.
returns true if it was success and errorMessage will be an empty string
returns false if it was not successful and errorMessage will contain an exception message.
Is this good style?
Update:
Lets say i do use the following method signature:
public static List<Poll> GetPolls()
and in that method, it doesn't catch any exceptions (so i depend the caller to catch exceptions). How do i dispose and close all the objects that is in the scope of that method? As soon as an exception is thrown, the code that closes and disposes objects in the method is no longer reachable.
That method is trying to do three different things:
Retrieve and return a list of polls
Return a boolean value indicating success
Return an error message
That's pretty messy from a design standpoint.
A better approach would be to declare simply:
public static List<Poll> GetPolls()
Then let this method throw an Exception if anything goes wrong.
This is definitely not an idiomatic way of writing C#, which would also mean that it probably isn't a good style either.
When you have a TryGetPolls method then it means you want the results if the operation succeeds, and if it doesn't then you don't care why it doesn't succeed.
When you have simply a GetPolls method then it means you always want the results, and if it doesn't succeed then you want to know why in the form of an Exception.
Mixing the two is somewhere in between, which will be unusual for most people. So I would say either don't return the error message, or throw an Exception on failure, but don't use this odd hybrid approach.
So your method signatures should probably be either:
IList<Poll> GetPolls();
or
bool TryGetPolls(out IList<Poll> polls);
(Note that I'm returning an IList<Poll> rather than a List<Poll> in either case too, as it's also good practice to program to an abstraction rather than an implementation.)
I believe
public static bool TryGetPolls(out List<Poll> polls)
would be more appropriate. If the method is a TryGet then my initial assumption would be there is reason to expect it to fail, and onus is on the caller to determine what to do next. If they caller is not handling the error, or wants error information, I would expect them to call a corresponding Get method.
As a general rule, I would say no.
The reason I say no is actually not because you're performing a TryGetX and returning a bool with an out parameter. I think it's bad style because you're also returning an error string.
The Try should only ignore one specific, commonly-encountered error. Other problems may still throw an exception with the appropriate exception message. Remember that the goal of a Try method like this is to avoid the overhead of a thrown exception when you expect a particular, single sort of failure to happen more frequently than not.
Instead, what you're looking for is a pair of methods:
public static bool TryGetPolls( out List<Poll> polls );
public static List<Poll> GetPolls();
This way the user can do what's appropriate and GetPolls can be implemented in terms of TryGetPolls. I'm assuming that your staticness makes sense in context.
Consider returning:
an empty collection
null
Multiple out parameters, to me, is a code smell. The method should do ONE THING only.
Consider raising and handling error messages with:
throw new Exception("Something bad happened");
//OR
throw new SomethingBadHappenedException();
No, from my point of view this is very bad style. I would write it like this:
public static List<Poll> GetPolls();
If the call fails, throw an exception and put the error message in the exception. That's what exceptions are for and your code will become much cleaner, more readable and easier to maintain.
Not really - I can see a number of problems with this.
First of all, the method sounds like you'd normally expect it to succeed; errors (cannot connect to database, cannot access the polls table etc) would be rare. In this case, it is much more reasonable to use exceptions to report errors. The Try... pattern is for cases where you often expect the call to "fail" - e.g. when parsing a string to an integer, chances are good that the string is user input that may be invalid, so you need to have a fast way to handle this - hence TryParse. This isn't the case here.
Second, you report errors as a bool value indicating presence or absence of error, and a string message. How would the caller distinguish between various errors then? He certainly can't match on error message text - that is an implementation detail that is subject to change, and can be localized. And there might be a world of difference between something like "Cannot connect to database" (maybe just open the database connection settings dialog in this case and let the user edit it?) and "Connected to database, but it says 'Access Denied'". Your API gives no good way to distinguish between those.
To sum it up: use exceptions rather than bool + out string to report messages. Once you do it, you can just use List<Poll> as a return value, with no need for out argument. And, of course, rename the method to GetPolls, since Try... is reserved for bool+out pattern.
The guidelines say to try to avoid ref and out parameters if they are not absolutely required, because they make the API harder to use (no more chaining of methods, the developer has to declare all the variables before calling the method)
Also returning error codes or messages is not a best practice, the best practice is to use exceptions and exception handling for error reporting, else errors become to easy to ignore and there's more work passing the error info around, while at the same time losing valuable information like stacktrace or inner exceptions.
A better way to declare the method is like this.
public static List<Poll> GetPolls() ...
and for error reporting use exception handling
try
{
var pols = GetPols();
...
} catch (DbException ex) {
... // handle exception providing info to the user or logging it.
}
It depends on what the error message is. For instance, if processing couldn't continue because the database connection wasn't available, etc., then you should throw an exception as other people have mentioned.
However, it may be that you just want to return "meta" information about the attempt, in which case you just need a way to return more than one piece of information from a single method call. In that case, I suggest making a PollResponse class that contains two properties: List < Poll > Polls, and string ErrorMessage. Then have your method return a PollResponse object:
class PollResponse
{
public List<Poll> Polls { get; }
public string MetaInformation { get; }
}
Depends on if an error is a common occurance or if it us truly an exception.
If errors are gunuinely rare and bad then you might want to consider having the method just return the list of polls and throw an exception if an error occurs.
If an error is something that is realtively common part of normal operations, as like an error coverting a string to an integer in the int.TryParse method, the method you created would be more appropriate.
I'm guessing the former is probably the best case for you.
It depends on how frequently the method will fail. In general, errors in .Net should be communicated with an Exception. The case where that rule doesn't hold is when the error condidition is frequent, and the performance impact of throwing and exception is too high.
For Database type work I think an Exception is best.
I'd restate it like this.
public static List<Poll> GetPolls()
{
...
}
It should probably be throwing an exception (the errorMessage) if it fails to retrieve the polls, plus this allows for method chaining which is less cumbersome than dealing with out parameters.
If you run FxCop, you'll want to change List to IList to keep it happy.
I think its fine. I would prefer though:
enum FailureReasons {}
public static IEnumerable<Poll> TryGetPolls(out FailureReasons reason)
So the error strings don't live in the data-access code...
C# Methods should really only do one thing. You're trying to do three things with that method. I would do as others have suggested and throw an exception if there is an error. Another option would be to create extension methods for your List object.
e.g. in a public static class:
public static List<Poll> Fill( this List<Poll> polls) {
// code to retrieve polls
}
Then, to call this, you would do something like:
List<Poll> polls = new List<Poll>().Fill();
if(polls != null)
{
// no errors occur
}
edit: i just made this up. you may or may not need the new operator in List<Poll>().Fill()
Please state your assumptions, constraints, desires/goals, and reasoning; we're having to guess and/or read your mind to know what your intentions are.
assuming that you want your function to
create the polls list object
suppress all exceptions
indicate success with a boolean
and provide an optional error message on failure
then the above signature is fine (though swallowing all possible exceptions is not a good practice).
As a general coding style, it has some potential problems, as others have mentioned.
There is also this pattern, as seen in many Win32 functions.
public static bool GetPolls(out List<Poll> polls)
if(!PollStuff.GetPolls(out myPolls))
string errorMessage = PollStuff.GetLastError();
But IMO it's horrible.
I would go for something exception based unless this method has to run 65times per second in a 3d game physics engine or someting.
Did I miss something here? The question asker seems to want to know how to clean up resources if the method fails.
public static IList<Poll> GetPolls()
{
try
{
}
finally
{
// check that the connection happened before exception was thrown
// dispose if necessary
// the exception will still be presented to the caller
// and the program has been set back into a stable state
}
}
On a design side note, I'd consider pushing this method into a repository class so you have some sort of context with which to understand the method. The entire application, presumably, is not responsible for storing and getting Polls: that should be the responsibility of a data store.

Categories

Resources