2

I would like to create three method with same method name and parameter which

public async Task <ObjectResponse> GenericMethod (object job) {
    return AObject.method(job). // where AObject.method(job) is return ObjectResponse
}

public async Task <TResult> GenericMethod<TResult> (object job) where TResult : new() {
    return BObject.method<TResult>(job) ?? new TResult(); // where BObject.method(job) is return Generic Type
}

public async Task <string> GenericMethod<String> (object job) {
    return CObject.method(job); // where CObject.method(job) is return string
}

I ve got the error on

   public async Task <String> GenericMethod<String> (object job) {
        return something..
    }

where is said the same signature is already declared, how do it fix it, as I don't want to use the other method name to do

Thank you

Carrie Kaski
  • 133
  • 7
  • 1
    It's really unclear what you're trying to achieve. I doubt that you *really* want to declare a generic method with a type parameter called `String`, but you've already got a non-generic method declaration... – Jon Skeet Aug 19 '23 at 07:12
  • Your third declaration makes no sense. It's exactly the same as the second one, simply with a different name for the generic type parameter. When you say `GenericMethod` there, you're not specifying the `String` class but rather a generic type that will be referred to as `String` within that method, just as it's referred to as `TResult` in the second one. It loosk like you want three methods where one returns type `ObjectResponse`, one returns type `String` and one returns an arbitrary type specified at run time... – jmcilhinney Aug 19 '23 at 07:20
  • ...In that case, only one of them should be generic, but that means that the other two cannot be overloads because they vary only by return type and not by parameter count or type. Basically, you need at least two different method names. Probably three would be most appropriate, not overloading one. The fact that you want to use overloading is irrelevant. – jmcilhinney Aug 19 '23 at 07:22
  • as String is a struct which cannnot new(), as I need to specified for this – Carrie Kaski Aug 19 '23 at 07:52
  • Ah. I see the issue. Please see this question: [Why aren't type constraints part of a method's signature?](https://stackoverflow.com/questions/9440888/why-arent-type-constraints-part-of-the-method-signature) – John Wu Aug 19 '23 at 07:55
  • @JohnWu, it will get complain : Cannot use sealed class 'System.String' as type parameter constraint – Carrie Kaski Aug 19 '23 at 08:32
  • @jmcilhinney, as I want to generic method where TResult is new() or TResult is string and find the way to do – Carrie Kaski Aug 19 '23 at 08:33
  • *"or TResult is string"*. That's not a generic method. What you're asking for makes no sense, which is why you can't do it. – jmcilhinney Aug 19 '23 at 08:40

3 Answers3

4

If I understand the problem correctly, you want the caller to only have to worry about a single method name, but when the return type is string you want to have a separate implementation.

The best solution of course is to write your code in a way where string doesn't need special handling, but there are cases where this is not possible. If that is your case, you can simply expose a single method but check the type and handle the logic separately, perhaps with a private method.

public async Task<TResult> GenericMethod<TResult>(object job) 
{
    if (typeof(TResult) == typeof(string))
    {
        return (TResult)(object)await ReadAsString();
    }
    else
    {
        return await ReadAsJson<TResult>() ?? default(TResult);
    }
}

private async Task<string> ReadAsString()
{
    //Your implementation
}

private async Task<T> ReadAsJson<T>()
{
    //Your implementation
}
John Wu
  • 50,556
  • 8
  • 44
  • 80
  • It's can, it complain Cannot convert expression type 'string' to return type 'TResult' on line : if (typeof(TResult) == typeof(string)) return await GenericMethodString(job); because the genericmethod return value if TResult is object, it will return httpresponseobject.Content.ReadFromJsonAsync() ?? new TResult(): if TResult is string , it will return httpresponseobject.Content.ReadAsStringAsync() – Carrie Kaski Aug 19 '23 at 08:27
  • Please see my edited answer. – John Wu Aug 19 '23 at 08:59
  • When I apply usage, as below: return await responseObject.GenericMethod(someobject); it get the error 'string' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'TResult' in the generic method – Carrie Kaski Aug 19 '23 at 09:08
  • I suppose you could get rid of the `new()` constraint and return `default(TResult)` instead of `new TResult()`. If that is acceptable see my revised answer. If you insist on returning a new instance you could also use `Activator.CreateInstance`. – John Wu Aug 19 '23 at 09:18
1

The Reason Why Your Code Might Not Work:

Both the second and third methods in your code are the same. The usage of String in the second method is not referring to the String class; instead, it is a type parameter that hides the String class. As a result, <String> and <TResult> are considered equivalent, making it impossible to use the same method name twice.

How to Correct:

If your goal is simply to make the code function without considering its functional significance, you can modify the parameter type of the second method as follows:

public async Task<ObjectResponse> GenericMethod(object job)
{
    return AObject.method(job); // where AObject.method(job) returns an ObjectResponse
}

public async Task<TResult> GenericMethod<TResult>(string job) where TResult : new()
{
    return BObject.method<TResult>(job) ?? new TResult(); // where BObject.method(job) returns a Generic Type
}

public async Task<string> GenericMethod<String>(object job)
{
    return CObject.method(job); // where CObject.method(job) returns a string
}

Please note that the provided code remains unchanged.

Seyfi
  • 1,832
  • 1
  • 20
  • 35
  • it can't , because all parameter is same, object is just an example it can be public async Task GenericMethod(socketClient client) {} public async Task GenericMethod(socketClient client) {} public async Task GenericMethod(socketClient client) any way , I think @John Wu answer seem helpful, but thank you for your help – Carrie Kaski Aug 19 '23 at 10:53
0

If I understand correctly, you might solve this problem by making your local function static and making the method private like this:

 private static async Task<String> GenericMethod1<String>(object job)
    {
        Range range = something..;
        return range;
    }

This might not work because I might not have understood your concept.

kimiahdri
  • 35
  • 1
  • 13