如何为c#7元组中的方法参数指定默认值?

如何为c#7元组中的方法参数指定默认值?,c#,.net,parameters,default,c#-7.0,C#,.net,Parameters,Default,C# 7.0,在C#中,您可以定义默认参数,如下所述。我在玩元组和C#7(在启用首选项->查询->使用Roslyn程序集时使用),如下所示: void Main() { var result=AddTuples((1, 2), (3, 4)); Console.WriteLine($"Result is: {result}"); } (int x, int y) AddTuples((int x, int y) a, (int x, int y) b) {

在C#中,您可以定义默认参数,如下所述。我在玩元组和C#7(在启用
首选项->查询->使用Roslyn程序集时使用),如下所示:

void Main()
{   
    var result=AddTuples((1, 2),  (3, 4));
    Console.WriteLine($"Result is: {result}");
}

(int x, int y) AddTuples((int x, int y) a,  (int x, int y) b)
{
    return (a.x + b.x,  a.y + b.y);
}
这很好,它显示了a和b的总和:

结果是:(4,6)

现在我试图修改
AddTuples
,使其具有默认参数,但不知何故,我无法弄清楚如何使用。我尝试的是:

(int x, int y) AddTuples2((int x, int y) a = (0, 0),  (int x, int y) b = (0, 0))
{
    return (a.x + b.x,  a.y + b.y);
}
但我收到了错误信息:

CS1736“a”的默认参数值必须是编译时常量

CS1736“b”的默认参数值必须是编译时常量

(在线试用)

我做错了什么


更新 谢谢你提供的精彩答案,我学到了很多。让我总结一下:要使元组参数具有默认值,有3种可能的选项:

  • 老式方法:重载方法,在方法体中提供默认值。缺点:如果有2个以上的元组,重载会变得很麻烦
  • ,在方法体中提供默认值
  • 若要在方法的参数中允许2个以上的元组,请在方法体中提供默认值

  • 注意:选项1,2。四,。允许指定任何所需的默认值,而选项3。仅限于
    default
    关键字提供的默认值。

    a
    b
    不是常量。创建新实例的所有内容(无论是结构还是类)都不被视为常量,方法签名只允许常量作为默认值

    也就是说,没有办法从方法签名中默认元组,您必须创建一个单独的方法

    唯一的出路似乎是使用可为空的参数:

    (int x, int y) AddTuples2((int x, int y)? a = null, (int x, int y)? b = null)
    {
        (int x, int y) aNN = a ?? (0,0);
        (int x, int y) bNN = b ?? (0,0);
        return (aNN.x + bNN.x, aNN.y + bNN.y);
    }
    

    只要您对
    int
    组件的默认初始化为零感到满意,就可以指定默认值:

    public static (int x, int y) AddTuples(
        (int x, int y) a = default((int, int)), 
        (int x, int y) b = default((int, int)))
    {
        return (a.x + b.x, a.y + b.y);
    }
    
    不幸的是,您不能为元组的组件提供特定的默认值

    但是,对于您的特定示例(您希望默认设置为
    (0,0)
    ),这似乎足够了


    [增编]

    此特定示例的另一种方法是使用
    params
    数组:

    public static (int x, int y) AddTuples(params (int x, int y)[] tuples)
    {
        return (tuples.Sum(t => t.x), tuples.Sum(t => t.y));
    }
    
    然后你可以做:

    Console.WriteLine($"Result is: {AddTuples()}");                       // (0, 0)
    Console.WriteLine($"Result is: {AddTuples((1, 1))}");                 // (1, 1)
    Console.WriteLine($"Result is: {AddTuples((1, 1), (2, 2))}");         // (3, 3)
    Console.WriteLine($"Result is: {AddTuples((1, 1), (2, 2), (3, 3))}"); // (6, 6)
    

    VisualStudio 2017建议对Patricks的答案进行以下简化:

    (int x, int y) AddTuples2((int x, int y)? a = null, (int u, int v)? b = null)
    {
        (int x, int y) = a ?? (0,0);
        (int u, int v) = b ?? (0,0);
        return (x + u, y + v);
    }
    

    我想你将无法做到这一点,因为结构实例不能是常量,而元组实际上只是结构。创建另一个没有参数的方法,并从within@Jan-是的,我知道这总是可能的。我认为C#7的设计者实现了更多的语法糖…元组实际上只是一种结构,编译器接受一种特殊的初始化语法,例如(int x,int y)a=(0,0),结构通常不是编译时常量,因为没有任何东西禁止一个结构拥有一个产生任意副作用的构造函数,这反过来又与编译时的恒定性约束相矛盾。要实现所需的行为,您需要对该方法进行多个重载。@Matt它确实更优雅,但它是以装箱为代价的,如下所述:。我想这只是偏好的问题。在这种情况下,我个人更喜欢性能而不是优雅。很好的解决方案,帕特里克!注意:您不需要引入新的局部变量,
    a
    b
    可以像
    a=a??(0, 0);在函数体中。是的,但您必须执行
    a.Value.x
    然后。您是对的,在本例中
    返回(a.Value.x+b.Value.x,a.Value.y+b.Value.y)
    是必需的-但它可以工作,而且我相信它看起来更可读一些!:-)这与类似,但他实际上是通过检查null并指定所需的默认值来解决的。@Matt实际上,他必须将参数类型从
    (int,int)
    更改为
    (int,int)
    ,所以这有些不同。这种方法根本不改变参数类型(但仅限于默认为默认值,因此没有那么灵活)。我不知道您可以为tuples传递默认值。很高兴知道这也可以,如果您只需要
    (0,0)
    作为默认值,也可以。我给了你一票@C#7中的SergeyBerezovskiy这些元组是结构,所以你可以这样定义它们。很好的提示,这种方法看起来更简单,不需要指定
    aNN
    bNN
    ,而是在参数中引入变量
    x
    y
    u
    v
    ,然后使用它们。