5

I have some generic method

T SomeMethod(Func<T> func){
   T result = func();
     if (result != null)
       { //.....}
}

It works good if T is class. But what should I do if T is struct? How can I check if result == default(T) in case if T is struct?

P.S. I don't want to use the constraint where T: class or Nullable types.

3
  • What is the use of checking if a value type is equal to the default value, and how does this logically match an object being null? What if a reference type has just been constructed - is that equivalent? I think this can't be answered generically, but must be answered on a case-by-case basis depending on your scenario. Commented Oct 25, 2011 at 19:33
  • To add to @dlev default(T) where T : class == null Commented Oct 25, 2011 at 19:35
  • To expand on my earlier comment, if you're just trying to avoid an NRE, then JaredPar's answer tells you that you can simply write if(result != null). Commented Oct 25, 2011 at 20:10

3 Answers 3

3

If T is compiled to be a struct then the comparison with null will always evaluate to false. This is covered in section 7.9.6 of the C# language spec

If an operand of a type parameter type T is compared to null, and the runtime type of T is a value type, the result of the comparison is false.

Sign up to request clarification or add additional context in comments.

7 Comments

Interestingly when you compare nullable structs with null it still returns null.
Which version of the spec did you use? I read: "If B is a type parameter and at runtime the type parameter is a nullable type or reference type, the result is as if the operand of type B is boxed and then compared to null. " [ECMA 4th ed]
@CodeInChaos I'm reading the C# 3.5 language spec for reference here
@CodeInChaos: This is behavior that is specific to Nullable<T> (which is a struct itself), as is the ability to assign null. That's baked into the language (and perhaps the runtime; I'm not certain about that) and isn't something that can be duplicated on user types.
@JaredPar, do you mean if (result != null || result==false) ? Does it work for structs?
|
3

A more idiomatic way of doing this would be to follow the lead of things like int.TryParse.

public delegate bool TryFunction<T>(out T result);

T SomeMethod(TryFunction<T> func)
{
    T value;

    if(func(out value))
    {

    }
}

6 Comments

This doesn't follow int.TryParse's lead, but instead builds on it. I don't think this is idiomatic, but it isn't a bad idea. Whether it generically solves the original problem or just side-steps it is a different question (one I can't answer - check my comment on the OP, since I think the question can't be answered generically).
Func<out T, bool> won't compile. You would have to create new delegate type for that.
@svick: Good catch; I'm not in front of VS right now. Nonetheless, this should do the trick.
@MerlynMorgan-Graham: I'm curious how it doesn't "follow its lead". The common idea is to move the return value into an out parameter and return a bool indicating success. I'm calling it idiomatic because this technique is used in several places in the framework, and seems to fit the bill.
@Adam: Wasn't me w/ the downvote. I'm just being pedantic, wanting some more clarity on exactly which parts are idiomatic. The signature of the delegate is idiomatic (try-method), but taking a try-method, generic or not, and using it as a predicate isn't idiomatic. Tho it might be a good idea.
|
0

Consider using default(T):

private T SomeMethod<T>(Func<T> func)
{
  var result = func();
  if (result.Equals(default(T)))
  {
    // handling ...
    return default(T);
  }
  return result;
}

1 Comment

If T is a reference type, this will throw a NullReferenceException.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.