初始化IEnumerable< int>作为可选参数

本文关键字:参数 IEnumerable int 初始化 | 更新日期: 2023-09-27 17:51:08

在我的c#方法中有一个类型为IEnumerable<int>的可选参数。我可以用null以外的任何东西初始化它吗?例如,一个固定的值列表?

初始化IEnumerable< int>作为可选参数

No。您只能使用编译时间常量。你可以将in赋值为null,然后

void SomeMethod(IEnumerable<int> list = null)
{
    if(list == null)
        list = new List<int>{1,2,3};
}

下一个代码片段摘自Jon Skeet的著名C# in Depth书。371页。他建议使用null作为参数的not set指示器,这些参数可能具有有意义的默认值。

static void AppendTimestamp(string filename,
                            string message,
                            Encoding encoding = null,
                            DateTime? timestamp = null)
{
     Encoding realEncoding = encoding ?? Encoding.UTF8;
     DateTime realTimestamp = timestamp ?? DateTime.Now;
     using (TextWriter writer = new StreamWriter(filename, true, realEncoding))
     {
         writer.WriteLine("{0:s}: {1}", realTimestamp, message);
     }
}
使用

AppendTimestamp("utf8.txt", "First message");
AppendTimestamp("ascii.txt", "ASCII", Encoding.ASCII);
AppendTimestamp("utf8.txt", "Message in the future", null, new DateTime(2030, 1, 1));

没有-默认参数必须是编译时常量。

最好的方法是重载该方法。或者,将默认值设置为null,并在方法中检测null并将其转换为您想要的列表。

如何将其默认值设置为null,并在

方法中
numbers = numbers ?? Enumerable.Empty<int>();

numbers = numbers ?? new []{ 1, 2, 3}.AsEnumerable();

不,你需要一个编译时间常数。

但是你可以使用重载来解决:

public void Foo(int arg1)
{
      Foo(arg1, new[] { 1, 2, 3 });
}
public void Foo(int arg1, IEnumerable<int> arg2)
{
      // do something
}

既然你需要编译时间常量,你就必须将其设置为null

但是你可以在

方法中做以下操作
 list = list ?? new List<int>(){1,2,3,4};

我一直在使用公认的答案,但是我刚刚有了一个头脑风暴,我想分享一下会很有趣。

使用default()struct的语义,可以这样做:

public readonly struct EmptyEnumerable<T> : IEnumerable<T>
{
    public IEnumerator<T> GetEnumerator()
    {
        return Enumerable.Empty<T>().GetEnumerator();
    }
    public IEnumerable.GetEnumerator()
    {
         return GetEnumerator();
    }
}
// ...elsewhere...
public void Foo<T>(IEnumerable<T> bar = default(EmptyEnumerable<T>))
{
}

之所以有效,是因为结构体的default不是null,而是该结构体的一个实例,就好像它是用默认构造函数调用的一样。由于default是在编译时确定的,所以编译器对它很满意,并且它可以正常工作。

当然,您可以更改GetEnumerator的内容以返回您想要的任何内容,而不仅仅是Enumerable.Empty,这只是我的用例。

免责声明

我实际上没有在我的代码中使用它,因为担心装箱引起的问题。我只是想把这篇文章作为对c#工作原理的有趣探索。也许有办法解决装箱问题,如果我想到一个,我会回来更新。