通用类型 - 名称可以简化

时间:2016-10-16 10:09:27

标签: c# visual-studio generics visual-studio-2015

我正在使用Visual Studio 2015,我有两个以下的陈述。

Task<List<int>> taskWithInLineAction = new Task<List<int>>(() =>
{
    List<int> ints = new List<int>();
    for (int i = 0; i < 1000; i++)
    {
        ints.Add(i);
    }
    return ints;
});

Task<List<int>> taskWithFactoryAndState = Task.Factory.StartNew<List<int>>((stateObj) =>
{
    List<int> ints = new List<int>();
    for (int i = 0; i < (int)stateObj; i++)
    {
        ints.Add(i);
    }
    return ints;
}, 2000);

Vs2015警告我

Task.Factory.StartNew<List<int>>((stateObj)

可以简化为

Task.Factory.StartNew((stateObj)

我可以看到我甚至可以在没有任何类型的情况下使用它,VS从lambda表达式返回值类型推断泛型类型,如下所示:

Task taskWithFactoryAndState = Task.Factory.StartNew((stateObj) =>
{
    List<int> ints = new List<int>();
    for (int i = 0; i < (int)stateObj; i++)
    {
        ints.Add(i);
    }
    return ints;
}, 2000);

但这不适用于第一个声明。在这种情况下,VS强迫我包含泛型类型。

你能帮助我,为什么这两个表现不同?

enter image description here

2 个答案:

答案 0 :(得分:4)

这两个代码示例做了不同的事情。最简单的方法是在两个部分的功能上设置一个断点并按下F5。它会达到第二部分的断点,即使它低于第一部分。

现在解释一下:

第一个是创建通用对象,在调用构造函数时,必须明确说明您要创建的类型。

Task<List<int>> taskWithInLineAction = new Task<List<int>>(() =>
{
    List<int> ints = new List<int>();
    for (int i = 0; i < 1000; i++)
    {
        ints.Add(i);
    }
    return ints;
});

所以当你写new ...时,你必须指定什么类型。

但是,在第二部分中,您执行一个函数,它返回一个对象并将其分配给一个变量。

Task<List<int>> taskWithFactoryAndState = Task.Factory.StartNew<List<int>>((stateObj) =>
{
    List<int> ints = new List<int>();
    for (int i = 0; i < (int)stateObj; i++)
    {
        ints.Add(i);
    }
    return ints;
}, 2000);

此时任务已经执行并在后台运行。因为您没有直接实例化对象,Visual studio会告诉您可以推断返回类型,因此“名称可以简化”。

如果你看起来视觉工作室也说你可以await它虽然没有说到第一部分:

List<int> taskWithFactoryAndState = await Task.Factory.StartNew<List<int>>((stateObj) =>
{
    List<int> ints = new List<int>();
    for (int i = 0; i < (int)stateObj; i++)
    {
        ints.Add(i);
    }
    return ints;
}, 2000);

答案 1 :(得分:2)

简单的设计视角:

  • 如果使用Generic Constructor初始化对象,则需要强制提供类型,这就是流向参数的内容,这些参数需要严格遵守
  • 如果使用Generic Method初始化对象,则可以使用方法Output定义类型,并且需要通过返回的类型来遵守。

因此,上述两种情况下的角色转换

案例1:使用通用构造函数

使用Task类构造函数完成初始化,因为我们使用的是通用版本,因此Task<T>构造函数,请查看以下link的各种选项。重要的一点是,Task<TResult>类型将参数作为Func委托,TResult作为输出,其中输出的类型使用Task<TResult>进行映射,这就是为什么必须定义类型为Task类,在初始化期间,它不是相反的方式。无法使用Func委托作为参数,其返回类型不是TResult(按设计),因此强制执行严格类型检查。在这种情况下使用的构造函数如下。

Task<TResult>(Func<TResult>)

案例2:使用通用方法

在这种情况下,Task.Factory.StartNew<TResult>(Func<TResult>)方法用于创建Task对象,其中Task的返回类型由Func委托及其返回类型管理,因此,类型检查仍然是强制执行但与第一种情况相反,因此返回的任务应与Func委托具有相同的类型,请检查以下link

在Visual Studio的情况下,它能够从编译器中获取细微差别细节,它在每次修改时运行,并且可以建议,更改是可选的/强制的,因此提示用户执行某个操作,从而使可选项变灰代码