1

I'm writing a very simple extension method that attempts to cast objects from one type to another. The intent of having this method is very similar to Int32.TryParse(string, out int), which allows the user to see 1) if the conversion succeeded, and 2) what the converted object is, all in one line.

Because this method will deal exclusively with class objects, it's possible that the object to be cast is actually null. Null can be cast to any nullable type (at least that's what it looks like based on my testing), so technically the method would always succeed in that situation. On the other hand, trying to convert null doesn't serve a lot of purpose and is usually a sign of things gone wrong. Therefore, my question is: in the case of the supplied object being null, should I return true (the cast succeeded) or false (did not succeed)?

This is (more or less) the method in question:

public static bool TryGetAs<T>(this object obj, out T output) where T : class
{
    output = null;
    if (obj == null)
        return [true or false];

    output = obj as T;
    return output != null;
}
  • in the case of the supplied object being null, should I return true (the cast succeeded) or false (did not succeed)? -- Did the cast actually succeed or not? – Robert Harvey Dec 5 '16 at 21:52
  • Why would it be a sign that something is wrong to try to cast null to another type? Plenty of the casts I make are on potentially null values. – Servy Dec 5 '16 at 21:52
  • 1
    @RobertHarvey You absolutely can call an extension method on a null object. It will not NRE. – Servy Dec 5 '16 at 21:55
  • 2
    @Servy: Then why the hell does it fail in my own code? Shit, now you're going to make me prove something I already know. – Robert Harvey Dec 5 '16 at 21:58
  • 1
    @RobertHarvey Remember that extensions methods are just syntactic sugar for static method calls. There is no virtual dispatch. someVariable.SomeExtensionMethod(); is transformated by the compiler into the morale equavalent of ClassExtensionMethodIsIn.SomeExtensionMethod(someVariable);, which obviously is never going to NRE. – Servy Dec 5 '16 at 21:58
3

Look to what your clients want, and try to provide an abstraction that is useful. And if you are your own client, try to think critically about what you want as a client rather than as the implementer.

I would assert that at the point someone calls this they are now only interested in whether the item provides the API of the type (which null doesn't).

If you return true for null, your clients are IMNSHO very likely to have to do their own null check in conjunction with, and either before or after using, your method. Only in vary rare cases will they not need their own null check.

If you return false, they won't have to do their own null check.

Still, have a look at how clients use the function, and you'll have your answer.

  • Now you're violating the single responsibility principle though. You're both checking if the type is compatible and you're also checking if the value is not null. You also assume that null is never a sensible value, an assumption that may or may not be the case (or rather, may or may not always be the case). – Servy Dec 5 '16 at 22:08
  • 2
    @Servy: That's not what a "responsibility" is. – Robert Harvey Dec 5 '16 at 22:10
  • @Servy, well, that's interesting. There's hardly enough responsibility here to merit a method, and it is certainly not an API or encapsulation. Further, I guess the built-in as violates that as well, since null -> null even though it is compatible. – Erik Eidt Dec 5 '16 at 22:10
  • It's too bad that Bob Martin elevated "SRP" to a "Principle" when he didn't even make "responsibility" a well-defined term. I've seen enough hand-wringing over that principle to fill a large book, especially from developers who don't know their primary language well enough yet to properly evaluate their code in terms of SRP. – Robert Harvey Dec 5 '16 at 22:11
  • @Servy, however, perhaps the OP is best served by popping up a bit and doing something more domain oriented rather than working at such a low and linguistic level. – Erik Eidt Dec 5 '16 at 22:12
1

If your input parameter is null you are not able to decide what is the right return value. Any return value would be as good as the other. It doesn't matter if it is null, true, false or "foobar".

Getting a special type of object from an arbitrary object is really weired. I really doubt the usecase. The point is that your generic method uses a language specific resolution that only works with related types... or at least it only makes sense with related types...

The difference between your method and the parse-method is: the int parse method provides a concrete algorithm to resolve the integer from a String. This algorithm is semantically well-defined.

Your algorithm may be technically well-defined but not semantically. You can easily see that if you try to put in an object of a custom type of yours and you want to return a String. I cannot imagine how this can make sense. How can this method do better than a toString method on the source object itself? The provided algorithm has no semantics.

So if you make the method generic and your algorithm does only make sense for SOME inputs and SOME outputs why should I confuse users of this method by pretending that it is doing beneficial stuff?

Avoid such kind of methods that pretend generic but are not.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.