需要参数命名以防止在相同的参数列表上出现歧义

Whi*_*ity 1 c# oop arguments ambiguous

考虑以下定义:

class Foo
{
    string Asd;
    List<int> Qwert;

    public Foo(string Bar, List<int> Baz = null)
    {
        // Set up instance from parameters
        this.Asd = Bar;
        this.Qwert = Baz ?? new List<int>;
    }

    public Foo(string Qwop)
    {
        // Code which sets up the instance based on what Qwop is
        // E.g.: take Asd and Qwert values from a previous storage
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我在Foo foo = new Foo("value");执行第二个构造函数时调用构造函数.

如何使编译器强制使用命名参数进行调用?因为两个构造函数的第一个参数都是a string,所以存在明显的模糊性.(无论如何,我无法逃避或解决这个问题,我们需要采取一种方式string.)

Foo foo = new Foo("value"); // NOT fine
Foo foo = new Foo(Bar: "value"); // Fine, first constructor
Foo foo = new Foo("value", new List<int> { 0, 1, 2 }; // Fine, as it is clearly 1st
Foo foo = new Foo(Qwop: "anothervalue"); // Fine, second constructor
Run Code Online (Sandbox Code Playgroud)

我想过声明一个额外的构造函数:

[Obsolete("Parameterization would be ambiguos. Please specify what string is by using named parameters", true)]
public Foo(string param)
{
    throw new ArgumentException();
}
Run Code Online (Sandbox Code Playgroud)

我认为这意味着如果没有命名参数,代码将调用此代码并且编译将失败.但是之前的构建失败了,因为

类型'Program.Foo'已经定义了一个名为'Foo'的成员,它具有相同的参数类型

显然,这是一个禁忌.但我的另一个尝试:

class Foo
{
    public Foo(IFooInvoker invoker)
    {
        if (invoker is FooInvokerBarBaz) { ... }
        else if (invoker is FooInvokerQwop) { ... }
    }
}

interface IFooInvoker { ... }

class FooInvokerBarBaz : IFooInvoker { ... }
class FooInvokerQwop : IFooInvoker { ... }

// And calling the whole from Main by
Foo foo = new Foo(new FooInvokerBarBaz("bar", new List<int> { 0, 1, 2 });
// or
Foo foo = new Foo(new FooInvokerQwop("qwop");
Run Code Online (Sandbox Code Playgroud)

看起来方式太复杂,是丑陋的,我认为违反了一个以上的设计原则.

Jon*_*eet 5

如何使编译器强制使用命名参数进行调用?

基本上你不能.它不是语言的一部分.

可以做的是使构造函数变为私有,而是公开静态工厂方法,这些方法解释了它们构造实例的内容.

public static Foo FromBarAndBaz(string bar, List<int> baz = null)
{
    return new Foo(bar, baz);
}

public static Foo FromQwop(string qwop)
{
    return new Foo(qwop);
}
Run Code Online (Sandbox Code Playgroud)

(为简单起见,您可能也希望baz构造函数中强制使用.)

请注意,我已更改参数名称以符合常规.NET命名约定.