Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass multiple arguments to a Func<> in C#

Tags:

c#

linq

This is from a programming test, so I'm sure that there is better way to do this, but the question required this specific answer.

I've a method Result which simply matches a predicate and returns a bool, and the predicate in question checks an array of strings to report if any string exceeds length 5.

static bool Result<T>(T[] values, Func<T, bool> predicate)
{
    if (values.Where<T>(predicate).Count() > 0)
        return true;
    else
        return false;
}

static bool StringLengthLessThan5(string str)
{
    return str.Length < 5;
}

Finally this is used like this -

bool val2 = Result(new string[5] { "asdf", "a", "asdsffsfs", "wewretete", "adcv" }, StringLengthLessThan5);

This works as expected, however now I need to use the same kind of code but parametrize the Func to allow a dynamic value for the string length, i.e my Func<string,bool> now needs to be Func<string,int,bool>

static bool StringLengthLessThanGivenNumber(string str,int length)
{
    return str.Length < length;
}

or alternately,

static Func<string, int, bool> FuncForDynamicStringlength = (s, i) => s.Length < i;

My question is this, in the spirit of keeping the calling code for the new Func the same, i.e. I still want to use -

Result(new string[5] { "asdf", "a", "asdsffsfs", "wewretete", "adcv" }, StringLengthLessThanGivenNumber);

but, how do I pass the parameters?

The Func now expects 2 parameters, the first being a string and the second being the int, how do I pass the first parameter? I can pass the int length to compare, but I'm stumped on the first parameter.

I realize that I can loop through my string[] and call the Func in a foreach like this (I know that this makes no sense in this specific instance since I'm overwriting the value of a bool, but I'm sure you get my question) -

foreach(string str in new string[5] { "asdf", "a", "asdsffsfs", "wewretete", "adcv" })
{
    bool val3_1 = StringLengthLessThanGivenNumber(str, 5);
}

but I would like to use my original code, if possible.

like image 816
Rakesh Avatar asked Dec 18 '22 06:12

Rakesh


1 Answers

Just wrap the predicate into lambda expression and pass in desired length using variable or constant like so:

int len = 5;
bool val1 = Result(new string[5] { "asdf", "a", "asdsffsfs", "wewretete", "adcv" }, x => StringLengthLessThanGivenNumber(x, len));
bool val2 = Result(new string[5] { "asdf", "a", "asdsffsfs", "wewretete", "adcv" }, x => StringLengthLessThanGivenNumber(x, 5));

Another way of solving this, would be defining extension method for string collections.

public static class StringCollectionExtensions
{
    public static bool HasLengthLessThan(this IEnumerable<string> collection, int length)
    {
        return collection.Any(x => x.Length < length);
    }
}

And then you could use it like this:

var testStrings = new string[5] {"asdf", "a", "asdsffsfs", "wewretete", "adcv"};

bool val3 = testStrings.HasLengthLessThan(6);
like image 111
Kaspars Ozols Avatar answered Dec 24 '22 00:12

Kaspars Ozols