如何返回一个类型化的元组取决于哪个变量不为空?

时间:2019-02-28 18:43:38

标签: c# .net functional-programming

我们如何实现模式匹配以返回元组?

当前方法签名

public static string Match(string nodeName, string nodeValue, string sourceParty, 
    string destinationParty, List<Translation> translations)

所需方法签名

public static (string, TypeOfMatch) Match(string nodeName, string nodeValue, 
    string sourceParty, string destinationParty, List<Translation> translations)

我有以下静态方法:

public static class Matcher
{
    public static string Match(string nodeName, string nodeValue, string sourceParty, 
        string destinationParty, List<Translation> translations)
    {
        //please excuse the pseudo code in these 3 lines
        var exactMatch = from.translations(where xyz).select.Take(1)
        var defaultMatch = from.translations.select(where abc).Take(1)
        var anySourceMatch = from.translations.select(where sss).Take(1)

        return exactMatch.FirstOrDefault() ??
            defaultMatch.FirstOrDefault() ??
            anySourceMatch.FirstOrDefault() ??
            nodeValue;
    }
}

我想知道返回的type匹配项(无论是精确/默认/ anySource)。

现在我们要返回string,但是返回的值应该是一个元组,例如(TypeOfMatch, string),其中TypeOfMatch是一个枚举,例如:

public enum TypeOfMatch
{
    Exact, Default, AnySource
}

,但是我们的return语句将类似于:

if (exactMatch.FirstOrDefault() != null)
    return (TypeOfMatch.Exact, exactMatch.First());

if (defaultMatch.FirstOrDefault() != null)
    return (TypeOfMatch.Default, defaultMatch.First());

// etc.

是否有更健壮的方法来对其中一个不为空的变量进行switch,然后返回对(TypeOfMatch, string)

1 个答案:

答案 0 :(得分:2)

您的方案面临的挑战是值元组是值类型,因此不能使用仅适用于可为null的类型的null-coalescing operator??进行组合。但是,您可以定义一个扩展方法,将您的值元组转换为 nullable 值类型,然后可以对它进行??

的处理。

我假设您的Translation类具有到string的隐式类型转换;否则,在构造值元组时,您需要调用ToString()或读取字符串属性。

public static class Matcher
{
    public static (TypeOfMatch, string) Match(
        string nodeName, string nodeValue, string sourceParty,
        string destinationParty, List<Translation> translations)
    {
        return
            translations.Where(xyz).Select(t => (TypeOfMatch.Exact, t)).FirstOrNull() ??
            translations.Where(abc).Select(t => (TypeOfMatch.Default, t)).FirstOrNull() ??
            translations.Where(sss).Select(t => (TypeOfMatch.AnySource, t)).FirstOrNull() ??
            (TypeOfMatch.NodeValue, nodeValue);
    }
}

public static class EnumerableExtensions
{
    public static T? FirstOrNull<T>(this IEnumerable<T> source)
        where T : struct
    {
        return source.Cast<T?>().FirstOrDefault();
    }
}