views:

148

answers:

2

In Delphi, if there was an exception during construction of an object: any allocated memory would be released and an exception would be thrown. For example, the following was guaranteed to either return a valid Camera object, or throw an exception:

Camera c = new Camera();

You never had to check the resulting variable for null:

Camera c = new Camera();
if (c == null)
   throw new Exception("Error constructing Camera") //waste of time

Is the same true in the CLR?

And are there other syntatical constucts where a return value is guaranteed to either be valid, or throw an exception?

  • Creating structures (e.g. Rectangle)?
  • getting a member of an enumeration?
  • the result of Object.ToString()?
  • mathmatical operations?

In the case of performing math:

Int32 aspect = 1650.0 / 1080.0;
if (aspect == null) 
   throw new Exception("Division of two numbers returned null")
+1  A: 

Yes. I'd like to put it this way (as fail might mean logical failure too): If a constructor doesn't throw an exception, the return value is guaranteed to be non-null so you never have to perform such a check.

Creating structures (e.g. Rectangle): A struct can't be null at all (Nullable types are considered completely different types, i.e. typeof(int?) != typeof(int)). Calling a constructor for a structure would either fail by throwing an exception or return an instance.

Getting a member of an enumeration: An enum is a just a set of constants. There's nothing like "getting a member at runtime." It's substituted at compile time.

The result of Object.ToString(): Like any method, it can return any valid value for string type which includes null and could also throw an exception (in which case, it doesn't return a value at all).

Mathematical operations: All expressions will return a value or throw an exception. The return value can be any valid value for that type (e.g. Int32 can never be null).

Mehrdad Afshari
+2  A: 

A constructor in .Net is guaranteed to return a non-null instance of the type of the object. Whether or not the instance is valid depends on the individual semantics of the type.

Exceptions thrown in a constructor will not be arbitrarily swallowed by the CLR (though user code can swallow them). The CLR will propagate an exception just like exceptions thrown in any other method and the objects will eventually be properly garbage collected.

As for the other cases you mentioned

  • Creating structures: Structures by definition can't ever be null. Exceptions thrown in the constructor will propagate normally
  • Getting a member of an enumeration: Enumerations are strutures / value types under the hood and also won't ever be null
  • the result of Object.ToString(): This can (and sadly will) be null. String is a reference type and it's perfectly legal to return null from a ToString override (please don't).
  • Mathematical operations: This depends heavily on both the overflow setting of your project and the particular type being used (integral vs. floating point).

The mathematical question almost deserves an answer on it's own. On one hand the result of a mathematical operation on primitive types won't ever be null. But it can still be invalid. For instance, the following code won't throw but whether or not the result is valid depends highly on your specific scenario

float f1 = 1.0;
float f2 = f1 / 0;

At this point f2 is a very specific float value that doesn't represent a real number. Is it valid? Depends on your use case.

JaredPar