Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple generic methods with identical names and arguments, but different results and constraints

I'm currently rewriting parts of a custom RPC mechanism (which cannot be replaced by something else, so don't suggest that ;-) ). The arguments of a call are collected in a custom collection that uses a dictionary internally. There is a method T Get<T>(string) to retrieve a named argument. For optional arguments, I wanted to add a TryGet<T>(string) method that returns the argument or null if it doesn't exist, so that the calling code can provide a default value using the null coalescing operator. Of course, for a value type this doesn't work, but I could use T? instead, which is what I want.

So what I have is this:

public class Arguments
{
    // lots of other code here

    public T TryGet<T>(string argumentName) where T : class
    {
        // look up and return value or null if not found
    }

    public T? TryGet<T>(string argumentName) where T : struct
    {
        // look up and return value or null if not found
    }
}

With that, I'd like to be able to do the following:

return new SomeObject(
                      args.TryGet<string>("Name") ?? "NoName",
                      args.TryGet<int>("Index") ?? 1
                      );

Since the constraints are mutually exclusive, the compiler should be able to produce the correct code (it's always possible to infer the call from the generic type given at the call site). The compiler complains that the type already defines a member called "TryGet" with the same parameter types.

Is there any way to make something like this work without giving the two methods different names?

like image 675
Pepor Avatar asked Dec 03 '22 06:12

Pepor


2 Answers

Constraints are not part of the signature. thus the answer to your question is no.

like image 168
Sky Sanders Avatar answered Dec 18 '22 20:12

Sky Sanders


The way classes in the .NET Framework handle this scenario is TryGetValue with an out parameter. The return value is an indicator of whether the get was successful, where the out parameter contains the value requested (on success) or a suitable default value (on failure).

This pattern makes the implementation very simple for reference and value types. You would only need a single method to handle both scenarios.

For an example of this pattern, see Dictionary<TKey,TValue>.TryGetValue.

like image 38
Paul Turner Avatar answered Dec 18 '22 22:12

Paul Turner