【问题标题】:Possible to differentate between nothing passed, or one null passed to F(params String[] values)?可以区分什么都没有传递,或者一个 null 传递给 F(params String[] values)?
【发布时间】:2014-02-12 13:01:34
【问题描述】:

我有一个函数

public List<Item> Filter(params String[] valuesOrdered)
{
    //...
}

它充当所有Items 的过滤器。

public class Item
{
    List<String> propertiesOrdered;
    //...
}

所以如果我打电话给例如Filter("prop1"),然后所有Items 以​​"prop1" 作为第一个条目,它们的属性将被匹配。

如果我调用Filter(),那么所有Items 都应该返回。

我还需要能够匹配 null 值。因此,例如现在我可以调用Filter(null, null) 和所有Items 和null, null,因为它们的第一个属性将被匹配。

除了我打电话给Filter(null) 之外,所有这些都有效。其解释方式与Filter() 相同,但意图是前者应返回所有Items,null 作为其第一个属性,后者应返回所有Items。

我尝试定义一个重载来处理这个问题

public List<Item> Filter(String value)
{
    if(value == null)
        return Filter(new String[] {null});
    else
        return Filter(value);
}

但是当我调用Filter(null) 时,编译器只会显示Ambiguous Invocation 错误。

【问题讨论】:

  • 请注意,即使您的过载结果没有帮助,它也应该是public List&lt;Item&gt; Filter(String value) { return Filter(new[] {value}); }。这更简单,并且总是调用原始重载(以正确的方式),而在 value 为非空的情况下,您无限递归地调用自己。 (请注意,Filter(value)不是模棱两可的。)
  • @JeppeStigNielsen 啊,是的。幸好它一开始就没有建立,因为另一个电话:)

标签: c# overloading params params-keyword


【解决方案1】:

如果你放弃重载,那么这个:

Filter(null);

会这样调用:

string[] valuesOrdered = null;
Filter(valuesOrdered);

不是这样的:

Filter(new string[] { null });

所以,您可以检测到这一点,并且如果您希望它表现得好像您传递了一个包含单个 null 的数组,那么这就足够了:

public List<Item> Filter(params String[] valuesOrdered)
{
    valuesOrdered = valuesOrdered ?? new string[] { null };

    //...
}

请注意:

Filter();

实际上会这样称呼:

Filter(new string[0]);

所以您可以检测到两者之间的差异。

这是一个简单的LINQPad 程序,演示:

void Main()
{
    Filter();
    Filter(new[] { "a" });
    Filter("a");
    Filter(null);
}

public static void Filter(params string[] values)
{
    values.Dump();
}

输出:

【讨论】:

    【解决方案2】:

    你可以使用语法

    Filter((String)null)
    

    使用长度为一的数组以“扩展”形式调用方法。

    如果您不喜欢该语法,您可能需要定义一个常量

    const String NullStr = null;
    

    并使用

    Filter(NullStr)
    

    改为。

    PS!就个人而言,我更喜欢 string 而不是 String,但我在这里坚持你的约定,因为它与你的问题无关。

    【讨论】:

    • 没错,但调用者不一定知道这个细节,所以我认为这不是一个“干净”的解决方案。
    • 关于您的编辑:仍然定义了NullStr,调用者可能不知道它并且很容易传递null。在这种情况下,我更喜欢 Lasse 的回答。关于 PS:谢谢,是的,我只是更喜欢使用一致的语法来分隔关键字和类型(包括别名)。
    • @DavidS。好吧,调用者应该知道这一点。正如他应该知道string.Concat(null);string.Concat((string)null); 不同,Activator.CreateInstance(typeof(Uri), null);Activator.CreateInstance(typeof(Uri), (string)null); 不同,等等。这对于 C# 语言来说是通用的,如果调用者选择 C# 进行调用,他应该知道。在我看来,让 null 数组代表一个唯一条目为空的长度为一的数组是很奇怪的,正如 Karlsen 在他的回答中所做的那样。但我想这是一个品味问题。
    猜你喜欢
    • 2012-02-20
    • 1970-01-01
    • 1970-01-01
    • 2017-01-13
    • 1970-01-01
    • 2012-04-03
    • 2023-03-26
    • 1970-01-01
    • 2011-07-17
    相关资源
    最近更新 更多