Как передать предопределенные функции в качестве параметра другой функции? - PullRequest
0 голосов
/ 22 октября 2019

У меня есть два класса: TextElement, который является расширением селена с некоторыми текстовыми свойствами (Text возвращает строку элемента), а другой - ArrayTextElement, который в основном является массивом TextElement объектов.

/// <summary>
/// Finds the first element that matches the text
/// </summary>
public static TextElement Find(this ArrayTextElement<TextElement > list, string text)
{
    try
    {
        return list.Items.First(item => item.Text.Equals(text));
    }
    catch (Exception)
    {
        throw new NotFoundException($"Requested element with text: '{text}' wasn't found.");
    }
}

/// <summary>
/// Finds the first element that contains the text
/// </summary>
public static TextElement FindByContains(this ArrayTextElement<TextElement > list, string text)
{
    try
    {
        return list.Items.First(item => item.Text.Contains(text));
    }
    catch (Exception)
    {
        throw new NotFoundException($"Requested element with text: '{text}' wasn't found.");
    }
}

Реальная проблема заключается в том, что мне нужно объединить эти две функции в 1. Поэтому я хочу отправить функции Equals и Contains, которые выходят из String, в качестве параметра.

Ответы [ 3 ]

3 голосов
/ 22 октября 2019

Вы можете преобразовать оба метода в один, передав Func<string, bool> и используя эту функцию внутри вашего первого. Итак, то, что у вас есть сейчас, становится:

public static TextElement Find(this ArrayTextElement<TextElement> list, Func<string, bool> predicate)
{
    try
    {
        return list.Items.First(item => predicate(item.Text));
    }
    catch (Exception)
    {
        throw new NotFoundException($"Requested element with text: '{text}' wasn't found.");
    }
}

И для того, чтобы вызвать его с помощью Contains или Equals, вы должны сделать это:

public void UsingTheMethod()
{
    ArrayTextElement<TextElement> list = new ArrayTextElement<TextElement>();
    string someText = string.Empty;
    Find(list, s => s.Equals(someText));
    Find(list, s => s.Contains(someText));
}
2 голосов
/ 22 октября 2019

Вы можете просто передать Func<string, bool> следующим образом:

public static TextElement Find(this ArrayTextElement<TextElement> list, Func<string, bool> predicate)
{
    try
    {
        return list.Items.First(item => predicate(item.Text));
    }
    catch (Exception)
    {
        throw new NotFoundException($"Requested element with text: '{text}' wasn't found.");
    }
}

И назвать его так:

var text = // whatever;
var element = elements.Find(s => s.Equals(text));
1 голос
/ 22 октября 2019

Если я вас правильно понимаю, вы можете передать дополнительный параметр, чтобы указать, хотите ли вы использовать точное совпадение или частичное. Следующее хорошо, если вы ищете только точные или частичные поиски. Другие ответы, приведенные здесь, гораздо более универсальны, но эту версию немного проще поддерживать.

public static TextElement Find(this ArrayTextElement<TextElement> list, string text, bool exactMatch)
{
    try
    {
        return list.Items.First(item => exactMatch ? 
            item.Text.Equals(text) :
            item.Text.Contains(text)
         );
    }
    catch (Exception)
    {
        throw new NotFoundException($"Requested element with text: '{text}' wasn't found.");
    }
}

Чтобы использовать ее:

TextElement textElem = list.Find("abcdef", [true|false]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...