C# – Extending a struct. Using helper classes rather than composition

ccompositiondesign-patternsobject-oriented

I have a struct which I want to add static methods to. Yes, you guessed right I'm talking about Datetime.

It's a pretty typical requirement to add MyCustomParse. It happens to return Datetime?, so it's not a constructor, but it's in that area, a static method that returns an instance. The content of this method has already been written and currently happy lives as a instance method of a class that uses it. I want to bring it out of that class so I can use it elsewhere.

Traditionally I would put it in a helper class (which is what I've done here), but apparently they're evil.

What I really want to do is tie Datetime.MyCustomParse(mystring). But the only way I can see is to make a new struct that composes Datetime. I then add in my method, write the implicit conversions and then put in all the other Datetime methods etc. This would be a pain to code (Being verbose also causes problems wrt xml docs and naive code coverage metrics, if that counts for anything).

I have considered extension methods, but I don't think the methods make sense on instances.

What is the strict OO position? Do I get a pass on writing methods that should belong to classes in separate helper classes when I want to extend structs in this fashion?

What is the pragmatic position (I'm not saying OO isn't pragmatic), is this code you would write, or have I missed a trick?

internal static class DateTimeHelper
{

    public static DateTime? MyCustomParse(string utcDateTimeText, string[] formats)
    {
        DateTime utcDateTime;
        if (DateTime.TryParseExact(utcDateTimeText, formats, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out utcDateTime))
        {
            return utcDateTime;
        }

        return null;
    }
}

PS I know there are more nuanced views on helper classes, but I still feel I need to justify my use here.

Best Answer

What is the strict OO position?

"strict" is undefined in OO space?

What is the pragmatic position? I want to bring it out of that class so I can use it elsewhere. The content of this method has already been written and currently happy lives as a instance method of a class that uses it.

OO Rationalization

Well, one approach may be to think about creational design patterns. I see this as counterpoint to the "helper class" idea. I see the "helper" as a smorgasbord - incoherent in terms of domain object design.

But a Factory, Builder, etc. composes behavior within an object- a domain-coherent thing. How is this different from a helper class? Intent.

OO Pragmatism meets Intent

Refactor to turn the method into a delegate. You can declare the delegate at the namespace level if necessary.

Write a instance-building something that registers/binds/whatever the delegate method. I expect the method's implementation will be inside this something.

Somthing's purpose in life is to instantiate fully-realized objects of the class/struct. Something does not contain those "random" type-specific (but not instance-owned) helper methods.

And because of intent we do not want the pragmatic approach of a class static method - which you have already dismissed.