0

I a making a little program that wants to analyse the gender of German nouns in a corpus. For that I have created some methods with a string as return value. For instance, I want to check if there is a definite in front of the noun in the corpus and see if it contains "der", "die" or "das". Deepening on which it returns different values. Like below:

private string definitearticle()
{ 
    // code, where gender is the string which we return - if we can't determine
    // the gender it returns "Cannot determine"
    return gender;
}

private string indefinitearticle()
{ 
    // code, where gender is the string which we return - if we can't determine
    // the gender it returns "Cannot determine"
    return gender;
}

I want to loop each one of the methods one by one until I no longer get "Cannot determine" as the return value like below with a list of pointers to the methods (like in Storing a list of methods in C#):

var methods = new List<(System.Action check, string caption)>()
{
    (definitearticle, "Definite article"),
    (indefinitearticle, "Indefinite article"),
};

foreach (var method in methods)
{
    gender = method.check.Invoke();
    if (gender != "Cannot determine")
    {
        // store the outcome that was returned to a list
        break;
    }
}

The problem is that I do not know how to use a List with methods that have a return value (in this case a string). Could anyone help me out here?

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
KGB91
  • 630
  • 2
  • 6
  • 24
  • I noticed that you have a list of names and you want to search for one or more letters in it? is it right? – Masoud Sharifi Jan 16 '22 at 17:38
  • 2
    use Func instead of Action. Microsoft docs: https://learn.microsoft.com/en-us/dotnet/api/system.func-2?view=net-6.0 – Nathaniel Walser Jan 16 '22 at 17:43
  • 1
    I think I'd define an enum to represent the genders/cannot and then have a `new List>()` - I couldn't work out what the `caption` member of the tuple was for, but feel free to restore it if it's used elsewhere. The func `Func` takes a string param, which I presume is what you're going to pass in to examine.. – Caius Jard Jan 16 '22 at 17:49
  • (But if you were e.g. looping over the corpus which was a list of words represented as a string[], and passing an int index to examine, so that you can look at the N-1'th word to see if it's der/die etc then you'd need to be making methods that accepted a `string[], int` and returned `GenderEnum` so it'd be a `Func` - anyways, that's the pattern: `Func`, minimally just the TReturn – Caius Jard Jan 16 '22 at 17:57
  • Thanks! I am analysing wikipedia data line by line so it is for that names. Caption is just the caption of the function that found the right gender for statistical proposes when I write about the result. – KGB91 Jan 16 '22 at 18:04

1 Answers1

3

If you need to store a method as a type that has a return value, you should use Func<TResult> instead of Action. It works the same way as an action, except that you additionaly can input the return type as the last generic type. So if you for example had a method where it had two parameters with the types of int and bool and a return type of string, you would say

var myReturnMethod = new Func<int, bool, string>((intVal, boolVal) => intVal.ToString() + boolVal.ToString());

In your case, just replace your methods variable initialization with this code:

var methods = new List<(Func<string> check, string caption)>
    {
        (definitearticle, "Definite article"),
        (indefinitearticle, "Indefinite article"),
    };

Edit:

On request of the OP, here's how you'd initialize the methods variable if you only wanted it to contain a collection of the methods, without the caption:

        var methods = new List<Func<string>>
        {
            definitearticle,
            indefinitearticle,
        };

More info on Functions can be found at the official microsoft docs.

Despacito 2
  • 444
  • 2
  • 10