Search code examples
c#methodsoverloadingvoid

Allowing for the return of a void method call result in a void method


-REWORD-
I have a method with a few overloads that share its type, all meant as a way of enabling optional parameters / ways of representing them.
if i write them as

T doStuff(int a) => doStuff(a.ToString());
T doStuff(string b) => doStuff(null, b);
T doStuff(string? a, string b)
{
    T ret=realComputation();
    return ret;
}

I can change the 'T' part to anything (MyClass, MyClass2, string) and only edit the last overload.
I can also change T to void, as Lamdas allow for f() => voidTypedMethod().

void doStuff(int a) => doStuff(a.ToString());
void doStuff(string b) => doStuff(null, b);
void doStuff(string? a, string b)
{
    realComputation();
    return;
}

Now,
in the step between two overloads i need to convert their parameters, and therefore cannot use Lambdas (without horrible workarounds that would defeat the point of editing less parts).

 T doStuff(int a) {
    //cast to next overload doing some computations
    string computedString = a.ToString();
    return doStuff(computedString);
}
T doStuff(string b) => doStuff(null, b);
T doStuff(string? a, string b)
{
    T ret = realComputation();
    return ret;
}

if i was now to change the type to void the compiler would raise an error, as void methods cannot use return except for "return;"

I was wondering if there was some syntax that allowed me to leave the return voidReturningMethod() there, enabling the same quick-editing lamda's syntax allow for.
As void methods do not return null (return; <!=> return null) the compiler would have to translate "return voidRetMethod();" to "voidRetMethod(); return;"

the code that prompted the question:

    public void AppendMessage(string styleKey, string text)
        => AppendMessage(styleKey, null, text);
    public void AppendMessage(string styleKey, string? title, string body) {
        Debug.Assert(MessageFormatsMap.ContainsKey(styleKey));
        /*return*/ AppendMessage(MessageFormatsMap[styleKey], title, body);
        
    }
    public void AppendMessage(MessageFormat mf, string? title, string body)
    {
        box.AppendText($"{(title is null ? "" : $"[{title}]")}\n{body}", mf.ForeColor);
    }

I'll probably have this methods return their class instance in the future, to allow for chained calls. Which leads me to the "how can i add/edit the least amount of code in the future?"

I also see it as a way of stating that they're bound to return the same Type and result.

-ORIGINAL QUESTION-

I'm new to C# and i was wondering if there is some elegant way to code this behaviour:
I have a method with a few overloads that share its type, all meant as a way of enabling optional parameters / ways of representing them.

    public void AppendMessage(string styleKey, string text) => AppendMessage(styleKey, null, text);
    public void AppendMessage(string styleKey, string? title, string body) {
        Debug.Assert(MessageFormatsMap.ContainsKey(styleKey));
        return AppendMessage(MessageFormatsMap[styleKey], title, body); ;
    }
    public void AppendMessage(MessageFormat mf, string? title, string body)
    {
        box.AppendText($"{(title is null ? "" : $"[{title}]")}\n{body}", mf.ForeColor);
    }

At the moment the type is void, but that could change.
For this reason i'd like for each overload to return the method of its next overload, which i'm sure they'll keep sharing, so that i won't be forced to add the return statements later on, upon adding non-void type.

The first 'AppendMessage' definition doesn't raise any error, whilst the second (of course) does:

"CS0127: ~ AppendMessage has type void, a return keyword cannot be followed by an 'object expression'"

I browsed the web and the forum for an appropriate Attribute (as i cannot always use Lambda functions) but i didn't manage to find one.

Is there one? or some other way to accomplish this?
It would also be nice if i could explicitate the constraint that the three methods must share the same type.


Solution

  • I was wondering if there was some syntax that allowed me to leave the return voidReturningMethod() there ...

    No, there is no such trick. If Proposal: Allow Void type as a Generic parameter will ever be accepted and implemented the you would be able to pass void to your generic class type parameter, i.e.:

    class Base<T>
    {
        T doStuff(int a) => doStuff(a.ToString());
        T doStuff(string b) => doStuff(null, b);
    
        T doStuff(string? a, string b)
        {
            T ret = RealComputation(); // real computation
            return ret;
        }
    
        protected virtual T RealComputation() => default;
    }
    
    class Child : Base<void>
    {
    }
    

    Before that you are limited to workarounds like:

    class Child : Base<MyVoid>
    {
        protected override MyVoid RealComputation()
        {
            RealComputationVoid();
            return new MyVoid();
        }
        
        protected virtual void RealComputationVoid() {}
    }
    public struct MyVoid{}