【问题标题】:How to initialize KeyValuePair object the proper way?如何以正确的方式初始化 KeyValuePair 对象?
【发布时间】:2013-03-19 09:02:30
【问题描述】:

我在(以及其他人)this question 中看到人们想知道如何初始化 KeyValuePair 的实例,它应该看起来像这样。

KeyValuePair<int, int> keyValuePair = new KeyValuePair<int, int>
{ 
  Key = 1,
  Value = 2
};

它不起作用,好像属性不存在。 Intead,我需要像这样使用构造函数。

KeyValuePair<int, int> keyValuePair = new KeyValuePair<int, int>(1, 2);

诚然,语法较短,但令我困扰的是我不能使用初始化程序。我做错了什么?

【问题讨论】:

    标签: c# initialization


    【解决方案1】:

    你没有错,你必须使用初始化一个 keyValuePair

    KeyValuePair<int, int> keyValuePair = new KeyValuePair<int, int>(1, 2);
    

    您不能使用对象初始化语法即 { Key = 1, Value = 2 } 的原因是因为 Key 和 Value 属性没有 setter 只有 getter(它们是只读的)。所以你甚至不能这样做:

    keyValuePair.Value = 1; // not allowed
    

    【讨论】:

      【解决方案2】:

      字典有紧凑的初始化器:

      var imgFormats = new Dictionary<string, ChartImageFormat>()
      {
          {".bmp", ChartImageFormat.Bmp}, 
          {".gif", ChartImageFormat.Gif}, 
          {".jpg", ChartImageFormat.Jpeg}, 
          {".jpeg", ChartImageFormat.Jpeg}, 
          {".png", ChartImageFormat.Png}, 
          {".tiff", ChartImageFormat.Tiff}, 
      };
      

      在这种情况下,我用来将文件扩展名与图表对象的图像格式常量相关联的字典。

      可以从字典中返回单个键值对,如下所示:

      var pair = imgFormats.First(p => p.Key == ".jpg");
      

      【讨论】:

        【解决方案3】:

        KeyValuePair&lt;int, int&gt; 是一个结构体,幸运的是,它是 不可变 结构体。特别是,这意味着它的属性是只读的。所以,你不能为它们使用对象初始化器。

        【讨论】:

        • +1 'struct' 点解释了这一切。正如你所说,只读属性只是 KVP 是结构的结果
        • @dennis 它是一个不可变结构,因为它的属性是只读的,而不是相反。
        • @Phil:我知道,谢谢。关键是 KVP 是一个设计良好的结构,因为它是不可变的。当然,struct 本身并不等于immutability
        • @Phil 当然,但这通常会导致错误(例如尝试仅通过传递值而不是引用来更新方法中的属性)因此将属性设置为只读的良好做法
        • 当然,对于一个不可变的class来说,这完全一样,例如代码new Tuple&lt;int, int&gt; { Item1 = 1, Item2 = 2 }给出了完全相同的错误(连同Tuple&lt;,&gt; 没有构造函数重载的错误采用 0 个参数)。
        【解决方案4】:

        好的,你有答案了。作为替代方案,我更喜欢类似于Tuple 类的工厂模式,用于类型推断魔法:)

        public static class KeyValuePair
        {
            public static KeyValuePair<K, V> Create<K, V>(K key, V value)
            {
                return new KeyValuePair<K, V>(key, value);
            }
        }
        

        这么短就变短了:

        var keyValuePair = KeyValuePair.Create(1, 2);
        

        【讨论】:

          【解决方案5】:

          这是一个完成这项工作的示例

          KeyValuePair<int, int> kvp = new KeyValuePair<int, int>(1, 1);
          

          【讨论】:

            【解决方案6】:

            Key 和 Value 属性没有设置器。这就是为什么您不能在初始化程序中使用它们的原因。只需使用构造函数:) 你会没事的。

            【讨论】:

              【解决方案7】:

              我也更喜欢工厂模式。但是当我不得不在外面创建一对时,我发现这种方式更有用。这样我就可以支持任何简单到复杂的用例。

              这样我可以使用任何类型并从它的属性或任何我想要的谓词中生成键值对,但更干净。喜欢类似IEnumerable.ToDictionary(keySelector,valueSelector)的方式

              
                      public static KeyValuePair<TKey, TValue> CreatePair<TSource, TKey, TValue>(
                       this TSource source,
                       Func<TSource, TKey> keySelector, 
                       Func<TSource, TValue> valueSelector)
                      {
                          if (source is null)
                          {
                              throw new ArgumentNullException(nameof(source));
                          }
              
                          if (keySelector is null)
                          {
                              throw new ArgumentNullException(nameof(keySelector));
                          }
              
                          if (valueSelector is null)
                          {
                              throw new ArgumentNullException(nameof(valueSelector));
                          }
              
                          return new KeyValuePair<TKey, TValue>(
                                       keySelector.Invoke(source), 
                                       valueSelector.Invoke(source));
                      }
              
              

              而你使用。

              yourObject.CreatePair(
                      x=> x.yourKeyPropery, 
                      x=> SomeOperationOnYourProperty(x.yourValueProperty));
              

              【讨论】:

                【解决方案8】:

                KeyValue 属性是只读的,因此您不能在对象初始化程序中使用它们。

                C# programming guide 中查看此条目。

                【讨论】:

                  【解决方案9】:

                  你没有做错什么。 KeyValuePairs 属性是只读的。你不能设置它们。此外,没有空的默认构造函数。您需要使用提供的构造函数。

                  【讨论】:

                  • 没有默认构造函数是正确的。但是代码var test = new KeyValuePair&lt;int, int&gt;(); 仍然可以。原因是KeyValuePair&lt;,&gt; 是一个结构。对于结构,如果您使用带有零参数的new 对象表达式,则将创建默认值(也称为default(KeyValuePair&lt;int, int&gt;))。在这种情况下,键和值都是 default(int) 的对,它是零。
                  • 我认为这是不正确的。我的 IntelliSense 告诉我,我可以创建 new KeyValuePair(),无论它有什么用处。不是所有的类都应该有一个默认的空构造函数吗?还是在 Java 中...?
                  • @CRMconfusee 不,这不是 C# 中的类的要求,而是结构的要求。
                  猜你喜欢
                  • 1970-01-01
                  • 2021-11-02
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-07-23
                  相关资源
                  最近更新 更多