views:

43

answers:

3

It'd be nice if I could define a method like this:

public T GetItem<T>() where T : null
{
    if (someCondition<T>())
        return someCalculation<T>();
    else
        return null;
}

Then I could use this on reference types (e.g., object, string) as well as nullable value types (e.g., int?, double?): anything that can be assigned to null. But this isn't possible.

Then again, for all I know, maybe it is? I know there'a no null constraint like I just fantasized about; but is there some workaround or clever way of accomplishing this that just hasn't occurred to me?

+2  A: 

Personally, I would create two overloaded generic methods: one that accepts reference types and another that accepts nullable value types. Then you'll be able to call with either kind of parameter.

John Bledsoe
Yeah, I do this quite a bit as well. But this requires giving the methods different names, which is frustrating.
Dan Tao
A: 

It would depend on the generic usage in the someCondition and someCalculation methods. But this sounds like where the 'default' keyword could be used.

return default(T);
Jerod Houghtelling
Well, I'm concerned with scenarios where I would want to be able to distinguish success from failure on the basis of the return value being `null` or not. With `int`, for example, `default(int)` is just `0`, which could be a valid return value for a huge variety of functions.
Dan Tao
@Dan, that situation makes sense. I would probably follow the TryParse pattern --even though I despise output variables. I assumed you were well aware of the 'default' so my answer was pretty silly.
Jerod Houghtelling
+1  A: 

I used to never use output parameters, partly I think the syntax just felt clumsy. However, a few years ago I started using them more and they've become a common aspect of the code that I write.

I think this is the kind of function where I would really consider writing the function with an output parameter and a boolean return type, as shown below:

public bool GetItem<T>(out T value)
{
    if (someCondition<T>())
    {
        value = someCalculation<T>();
        return true;
    }
    else
    {
        value = default(T);
        return false;
    }
}

With this approach there is no need to restrict your generic parameter to reference type or a nullable type.

As I mentioned above, I originally felt that output parameter syntax was clumsy, but after I really started using it frequently I felt that the code that consumed my functions with output parameters was actually more accurate towards representing the problem that I was trying to solve, if that makes any sense.

Dr. Wily's Apprentice
I do this quite a bit myself as well. I suppose this is a fairly close alternative that captures the spirit of what I'm asking about, so +1.
Dan Tao
Since it seems this ends up being the most sensible pattern for this problem (in *my* opinion, anyway -- I know there are a lot of `out` parameter naysayers out there), I'm going to go ahead and accept this answer.
Dan Tao