0

I have a list with methods that I am calling from a loop like below (with the help of a previous question: Create a list with methods with a return value C#):

string method;

var methods = new List<(Func<string> analysismethod, string caption)>
{
    (definitearticle, "Definite article"),
    (indefinitearticle, "Indefinite article"),
};
for (int i = 0; i < methods.Count(); i++)
{
    string gender = methods[i].analysismethod.Invoke();
    if (gender != "Cannot determine")
    {
        method = methods[i].caption;
        break;
    }
}

What I want to do now is to add an optional argument (a string) to each of the methods in methods (so I can reuse them for other purposes as well) like in:

definitearticle (word = default)
{
}

However, when I try add the optional argument, I get these errors:

Error   CS1950  The best overloaded Add method 'List<(Func<string> analysismethod, string caption)>.Add((Func<string> analysismethod, string caption))' for the collection initializer has some invalid arguments
Error   CS1503  Argument 1: cannot convert from '(method group, string)' to '(Func<string> analysismethod, string caption)'

How can I solve this?

edit: The reason why I want to use them with a specified string sometimes is that I sometimes want to analyse them for a specific input, whereas I sometimes just want to check for a default position in a sentence that I store in a struct:

public string indefinitearticle(string word = default)
{       
    if (word == default) 
    {
        word = AnalysisData.wordBeforeNoun;
    }

    string gender = default;
    if (word == "eine")
    {
        gender = "Fem";
    }
    else if (word == "ein")
    {
        gender = "Non fem";
    }
    
    return string.IsNullOrEmpty(gender) ? "Cannot determine" : gender;
}
KGB91
  • 630
  • 2
  • 6
  • 24
  • Delegates should be for a single purpose. If the code you posted doesn't need the string, don't add it to those methods, use a new list of delegates with a different signature for the other purpose. – madreflection Jan 29 '22 at 21:03
  • Regarding the error message... parameter defaults are not part of the method signature. If the method has the parameter, any delegate pointing to it must have a matching signature as if you removed the default from the method. – madreflection Jan 29 '22 at 21:04
  • Use overloads instead of optional parameter (that actually what compile will do - generate corresponding overload methods) - than you can use both overloads for different purposes. `definitearticle() => definitearticle("default")` – Fabio Jan 29 '22 at 21:06
  • That is, the problem would be solved if I have the same optional arguments to all of the methods? That would be a nice solutions since I intend to do just that once I am finished with the first one. – KGB91 Jan 29 '22 at 21:06
  • @Fabio That would be a solution, but I do not want to do that either since I want to be able to reuse the same analysis methods just sometimes with some user defined words. – KGB91 Jan 29 '22 at 21:07
  • No, it would not be solved by that because delegates signatures don't consider parameter defaults. – madreflection Jan 29 '22 at 21:08
  • I updated the post a bit to show what I want to do. – KGB91 Jan 29 '22 at 21:13

1 Answers1

2

Introduce overload methods

public string DefiniteArticle(string param1, string param2)  
{
    // calculate and return "some string";
}

public string DefiniteArticle()
{
    return DefiniteArticle("default value1", "default value2");
}

Now with parameterless overload you are able to add it to the collection of Func<string> to satisfy it's type and use "original" method for other purposes.

var delagates = new Func<string>[] { DefiniteArticle }

Notice that delegate are types as any other int or string - for being able to add method to the collection of delegates method should be same type. Overload method allows us to "decorate" original method with the required delegate type

Fabio
  • 31,528
  • 4
  • 33
  • 72
  • Overloads will help to create an overload method which will satisfy delegate type. – Fabio Jan 29 '22 at 21:13
  • Yes, but I want the calculations to be exactly the same - I just want to be able to change the input if I am not going for the default case. – KGB91 Jan 29 '22 at 21:14
  • 1
    @KGB91, overload methods doing exactly what you are trying to achieve _change the input if I am not going for the default case_ – Fabio Jan 29 '22 at 21:15
  • Yes, but then I will have to do have the calculations duplicated since the only thing I want to do is to have another input, the calculations will be exactly the same. – KGB91 Jan 29 '22 at 21:24
  • 1
    What you mean by "duplicated calculation", calculation will exists in one method and will be called by overload. – Fabio Jan 29 '22 at 22:13
  • Ah, I see... I call the function with the calculations if I do not want specify an argument. That is indeed a creative workaround. – KGB91 Jan 29 '22 at 22:25