【问题标题】:Safe convert function安全转换功能
【发布时间】:2016-10-21 14:43:43
【问题描述】:

谁能解释一下这段代码,尤其是我不确定作为参数的泛型函数是如何工作的:

result.Notes= orderInfo.Notes.SafeConvert(x => (Communication.OrderNotes)x);            

public static TOut[] SafeConvert<TIn, TOut>(
        this TIn[] input,
        Func<TIn, TOut> converter)
    {
        if (input == null)
        {
            return null;
        }

        return input
            .Where(i => i != null)
            .Select(converter)
            .ToArray();
    }

【问题讨论】:

  • “我不确定作为参数的泛型函数是如何工作的”你在说Select(converter)吗?
  • 请阅读How to Ask 并详细说明您需要帮助的具体部分。这种方法似乎也是Cast&lt;T&gt;() 方法的一种无可救药的复杂替代方案。但现在是星期五,我的内置编译器可能关闭了。

标签: c#


【解决方案1】:

SafeConvert 是一个通用的extension method。第一个参数(泛型类型 TIn 的数组)是在对某种类型的数组调用方法时隐式添加的(在这种情况下可能是注释?)。该方法还需要一个函数作为参数。此函数必须采用 TIn 类型的实例并返回 TOut 实例。因此,您将在某种类型的数组上调用此方法,提供 lambda 表达式或委托函数,它将返回您提供的函数返回的任何类型的数组。它通过使用 Linq 过滤掉空值,通过该方法运行数组中的每个项目,然后将这些项目的枚举作为数组返回。

在您给出的实现中,它采用“orderInfo”的“Notes”并将它们显式转换为“CommunicationOrderNotes”。

这是调用该方法的另一种方式。

var decimals = new [] {5, 3, 2, 1}.SafeConvert(someInt => (decimal) someInt);

【讨论】:

  • 谢谢 Timothy。为什么泛型方法 "SafeConvert" 有 2 个类型参数 - 它只能有 SafeConvert 吗?什么定义了 括号中的类型数量?第二,Func转换器没有任何输入参数,否则应该是“Func转换器(TIn, par1, par2,..)”?如果没有输入参数,如何对 TIn 进行操作 - 你能解释一下吗?
  • SafeConvert 需要 2 个基于其逻辑的泛型,一个代表你来自哪里,另一个代表你要去哪里。根据所涉及的唯一类型的数量,一个函数可以有尽可能多的泛型(一些函数可以有两位数的类型)。设计方法或泛型类的开发人员确定泛型的数量。此外, Func 只是一个方法定义,它确实有一个输入参数,因为 Func 接受输入并返回输出(除了最后一个之外的所有泛型都被视为输入类型,而最后一个是输出)。
【解决方案2】:

这就是所谓的extension method。它是一个静态函数,允许您在不修改原始代码的情况下向类型“添加”方法。它有点类似于Decorator Pattern,但controversy 是关于它是否实际上是该特定模式的实现。

“在底层”,至少,扩展方法只是调用静态方法的“语法糖”,但您可以将它们当作扩展对象(在本例中为数组)的实例方法来调用。

&lt;TIn, TOut&gt; 部分意味着 TInTOut 是您尚未指定的某种类型(但您打算在使用班级)。要了解其目的,请考虑链接列表 - 实际上,整数链接列表的实现与字符串链接列表的代码没有任何不同,因此您希望它是您的情况可以创建一个类并稍后指定您想要一个整数列表或字符串列表或其他任何内容。您肯定希望必须为每一种可能的对象类型创建一个实现——这将需要大量的冗余代码。

现在,对于 LINQ 查询:

return input
        .Where(i => i != null)
        .Select(converter)
        .ToArray();

LINQ(语言集成查询)是一种使用单一语法查询不同类型集合的机制。您可以使用它来查询 .NET 集合(就像他们在这里所做的那样),例如 XML documentsdatabases

LINQ 查询采用某种anonymous function 并以某种方式将运算符应用于集合(见下文)。

通过这个查询;

.Where(i => i != null)

顾名思义,Where 应用过滤器。当应用于集合时,它返回第二个集合,其中包含第一个集合中与过滤条件匹配的所有元素。

i => i != null

bit 是充当过滤器的匿名函数。基本上,这就是说“给我一个集合,其中包含数组中所有不为空的成员。”

Select 方法将转换应用于集合的每个元素,并将结果作为第二个集合返回。在这种情况下,您将作为参数传入的任何转换应用到方法。

将代码视为数据可能听起来有点奇怪,但在 F#、Lisp 和 Scala 等其他一些语言中,这实际上是非常常规的。 (“Under the hood”,C# 以面向对象的方式实现了这种行为,但效果是一样的)。

因此,此函数的基本思想是将一种类型的数组转换为第二种类型的数组,过滤掉所有的空引用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-21
    • 2019-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-14
    相关资源
    最近更新 更多