如何正确初始化 KeyValuePair 对象?

我在 这个问题中看到过,人们想知道如何初始化 键值对的一个实例,它应该是这样的。

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

它不工作,好像属性不存在一样。相反,我需要像这样使用构造函数。

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

不可否认,语法较短,但我不能使用初始化程序,这让我感到困扰。我做错了什么?

84272 次浏览

The Key and Value properties are read-only, therefore you can't use them in an object initializer.

See this entry in the C# programming guide.

KeyValuePair<int, int> is a struct, and, fortunately, it is immutable struct. In particular, this means that its properties are read only. So, you can't use object intializer for them.

You aren't doing something wrong. The KeyValuePairs properties are read-only. You cannot set them. Additionally, there is no empty default constructor. You need to use the constructor provided.

You are not wrong you have to initialise a keyValuePair using

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

The reason that you cannot use the object initialisation syntax ie { Key = 1, Value = 2 } is because the Key and Value properties have no setters only getters (they are readonly). So you cannot even do:

keyValuePair.Value = 1; // not allowed

The Key and Value properties have no setters. Thats why you can't use them in the initializer. Just use the constructor :) and you'll be fine.

Ok you have the answers. As an alternative, I prefer factory pattern similar to Tuple class, for type inference magic :)

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

So short becomes shorter:

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

Here goes an example that does the job

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

Dictionaries have compact initializers:

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

In this case the dictionary i used to associate file extensions with image format constants of chart objects.

A single keyvaluepair can be returned from the dictionary like this:

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

I also prefer factory pattern. But I found this way much more to be more useful when I had to create a pair outside. This way I can support any simple to complex use case.

This way I could use any Type and make KeyValue Pairs from its properties or any predicate I want, But cleaner. Like the way similar to 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));
}


And you use.

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