99

I've seen in (amongst others) this question that people wonder how to initialize an instance of KeyValuePair, which expectedly should look like this.

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

It doesn't work, as if the properties aren't there. Intead, I need to use the constructor like this.

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

Admittedly shorter syntax but it bothers me that I can't use the initializer. What am I doing wrong?

asked Mar 19, 2013 at 9:02

9 Answers 9

109

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
answered Mar 19, 2013 at 9:08
Sign up to request clarification or add additional context in comments.

Comments

32

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");
answered Sep 19, 2017 at 22:14

Comments

15

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.

answered Mar 19, 2013 at 9:06

7 Comments

+1 the 'struct' point is what explains it all. As you say, read only properties are just a consequence of KVP being a struct
@dennis it's an immutable struct because it's properties are read-only, not the other way round.
@Phil: I know this, thanks. The point is that KVP is a well-designed struct, because it is immutable. Of course, struct itself doesn't equal immutability.
@Phil of course, but this often leads to errors (like trying to update a property in a method just by passing the value and not the reference) Hence the good practice of making the properties read-only
Of course, this is exactly the same for an immutbale class, for example the code new Tuple<int, int> { Item1 = 1, Item2 = 2 } gives the exact same error (together with an error that no constructor overload for Tuple<,> takes 0 arguments).
|
15

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);
answered Jun 12, 2013 at 20:48

1 Comment

Since 2017, this static method Create has been a part of .NET (but not .NET Framework), so you do not have to write the method yourself anymore.
8

Here goes an example that does the job

KeyValuePair<int, int> kvp = new KeyValuePair<int, int>(1, 1);
Roman Marusyk
24.8k27 gold badges83 silver badges127 bronze badges
answered Jun 5, 2015 at 20:06

Comments

5

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.

answered Mar 19, 2013 at 9:08

Comments

3

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));
answered Sep 18, 2020 at 9:42

Comments

1

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.

answered Mar 19, 2013 at 9:06

Comments

1

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.

answered Mar 19, 2013 at 9:06

3 Comments

It is correct that there is no default constructor. However the code var test = new KeyValuePair<int, int>(); will still be OK. The reason is that KeyValuePair<,> is a struct. And for a struct, the default value (also called default(KeyValuePair<int, int>)) will be created if you use a new object expression with zero arguments. In this case, a pair where both key and value are default(int) which is zero.
I believe that's incorrect. My IntelliSense tells me that I can create new KeyValuePair(), whatever that might be good for. Aren't all classes supposed to have a default empty constructor? Or was it in Java...?
@CRMconfusee no thats not a requirement for classes in C#, but for structs.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.