【问题标题】:What is the right way to initialize a non-empty static collection in C# 2.0?在 C# 2.0 中初始化非空静态集合的正确方法是什么?
【发布时间】:2009-01-05 16:37:02
【问题描述】:

我想在我的 C# 类中初始化一个静态集合 - 像这样:

public class Foo {
  private static readonly ICollection<string> g_collection = ???
}

我不确定这样做的正确方法;在 Java 中,我可能会这样做:

private static final Collection<String> g_collection = Arrays.asList("A", "B");

C# 2.0 中有类似的构造吗?

我知道在 C#/.NET 的更高版本中,您可以使用集合初始化器 (http://msdn.microsoft.com/en-us/library/bb384062.aspx),但目前我们的系统不支持迁移。

为了澄清我最初的问题 - 我正在寻找一种简洁地声明一个简单静态集合的方法,例如一个简单的字符串常量集合。对于更复杂的对象的集合,静态初始化风格的方式也非常好。

谢谢!

【问题讨论】:

    标签: c# collections


    【解决方案1】:

    如果我完全理解您的问题,似乎其他人没有抓住重点,您希望以与 Java 类似的方式创建一个静态集合,因为您可以在一行代码中声明和填充,而无需创建一个专用方法来执行此操作(根据其他一些建议)。这可以使用数组文字来完成(写成两行以防止滚动):

    private static readonly ICollection<string> Strings = 
      new string[] { "Hello", "World" };
    

    这会一次性声明并使用项目列表填充新的只读集合。在 2.0 和 3.5 中工作,我测试了它只是为了更加确定。

    在 3.5 中,虽然您可以使用类型推断,但您不再需要使用删除更多击键的 string[] 数组:

    private static readonly ICollection<string> Strings = 
      new[] { "Hello", "World" };
    

    请注意第二行中缺少的“字符串”类型。字符串是从数组初始值设定项的内容自动推断出来的。

    如果您想将其填充为列表,只需将 new string[] 更改为 new List a la:

    private static readonly ICollection<string> Strings = 
      new List<string>() { "Hello", "World" };
    

    当然,因为你的类型是 IEnumerable 而不是特定的实现,所以如果你想访问特定于 List 的方法,例如 .ForEach(),你需要将其转换为 List:

    ((List<string>)Strings).ForEach(Console.WriteLine);
    

    但为可迁移性付出的代价很小 [这是一个词吗?]。

    【讨论】:

    • 是的,这是我的意图 - 我将编辑问题以使其更清楚。谢谢!
    【解决方案2】:

    静态构造:

    public class Foo
    {
        private static readonly ICollection<string> _collection;
    
        static Foo()
        {
            _collection = new List<string>();
            _collection.Add("One");
            _collection.Add("Two");
        }
    }
    

    但请注意,在这种情况下,您可以内联初始化集合(推荐用于performance reasons):

    private static readonly ICollection<string> _collection = new List<string>(new string[] { "One", "Two" });
    

    这真的取决于你的初始化代码有多复杂。

    【讨论】:

    • 您可以通过进一步调整初始化来进一步增强代码的可读性: ... = new List() { "one", "two" };
    【解决方案3】:

    也许你可以调用一个静态方法:

    public class Foo
    {
        private static readonly ICollection<string> g_collection = initializeCollection();
    
        private static ICollection<string> initializeCollection()
        {
            ... TODO allocate and return something here ...
        }
    }
    

    或者,拥有一个静态构造函数(正如其他人所建议的那样)可能是等效的,甚至更惯用。

    【讨论】:

      【解决方案4】:

      除了静态构造函数之外,这也可以工作

          public class Foo
          {
              private static readonly ICollection<string> _collection = 
                    new List<string>(new string[] { "elem1", "elem2", "...", "elemn" });
          }
      

      【讨论】:

        【解决方案5】:

        我能想到的唯一方法是拥有一个静态构造函数。因此,首先在类级别新建一个新集合,然后在静态构造函数中向其中添加所有值。

        【讨论】:

          【解决方案6】:

          您可以声明一个自定义集合类并向其添加您自己的 ctor...

            public class MyFooCollection: Collection<string>
             {
                public MyFooCollection(string[] values)
                {
                    foreach (string s in values)  base.Add(s); 
                }
             }
          

          然后在你的客户端代码中你可以写

            private static final MyFooCollection g_collection = 
                   new MyFooCollection(new string[] {"A", "B"});
          

          【讨论】:

            【解决方案7】:

            使用静态构造函数如下:

            public class Foo
            {
                static readonly ICollection<string> g_collection;
            
                // Static constructor
                static Foo()
                {
                    g_collection = new List<string>();
                    g_collection.Add("Hello");
                    g_collection.Add("World!");
                }
            }
            

            【讨论】:

              【解决方案8】:

              我喜欢使用IEnumerable&lt;T&gt;.ToList()
              此外,如果您的收藏应该是只读的,您可以使用System.Collections.ObjectModel.ReadOnlyCollection

              private readonly ICollection<string> collection = new string[] { "a", "b", "c" }.ToList();
              
              private readonly ReadOnlyCollection<string> collection2 = new ReadOnlyCollection<string>(new string[] { "a", "b", "c" });
              

              编辑:
              再说一次,如果您将它用作 ICollection,您可以简单地使用数组构造函数(因为 T[]IList&lt;T&gt;ICollection&lt;T&gt;)。请记住,在这种情况下,许多更改方法(例如 Add)都会失败:

              private readonly ICollection<string> = new string[] { "a", "b", "c" };
              

              编辑#2: 我刚刚意识到 ToList 是一个扩展函数,只能在 C# 3.0 中使用。您仍然可以使用 List 构造函数:

              private readonly IList<string> = new List<string>(new string[] { "a", "b", "c" });
              

              不过,对于只读列表,我更喜欢 ReadOnlyCollection

              【讨论】:

                【解决方案9】:

                你有两个选择:

                1. 使用静态方法的返回值来初始化集合。

                2. 使用静态构造函数创建集合,填充它并将其初始化为静态变量。

                从性能的角度来看,选项 1 更好,因为对于静态构造函数,运行时必须在每次访问类之前检查是否调用了静态构造函数。

                【讨论】:

                  猜你喜欢
                  • 2013-08-08
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-12-26
                  • 2022-01-21
                  • 1970-01-01
                  • 2013-08-08
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多