前几天自学了keyvaluepair,在网上找到一篇很好的Blog ,所以转载过来共享。
转载地址:http://www.cnblogs.com/
C# KeyValuePair
KeyValuePair stores two values together. It is a single
generic struct. The KeyValuePair type in System.Collections.Generic is simple
and always available. It is used internally in Dictionary.
Example
First, this example uses KeyValuePair in a List, which is also in
System.Collections.Generic. This is useful for storing pairs of values in a
single List. You could use two separate Lists, but that can complicate
matters.
Here:We initialize a new List of type
KeyValuePair.
This shows the required syntax form.
Note:Inside the brackets in the KeyValuePair, there
are two types separated by a comma (string, int).
Program that uses KeyValuePair: C#using System;
using System.Collections.Generic;class Program
{
static void Main()
{
// Shows a List of KeyValuePairs.
var list = new List<KeyValuePair<string, int>>();
list.Add(new KeyValuePair<string, int>("Cat", 1));
list.Add(new KeyValuePair<string, int>("Dog", 2));
list.Add(new KeyValuePair<string, int>("Rabbit", 4));foreach (var element in list)
{
Console.WriteLine(element);
}
}
}Output
[Cat, 1]
[Dog, 2]
[Rabbit, 4]
Also, we can create a new KeyValuePair with its
constructor. The constructor is shown in the List.Add calls. The KeyValuePair‘s
constructor returns the new KeyValuePair, and that instance is added.
Note:Instead of a List, you could use an array here.
You can specify the KeyValuePair<string, int> as the type of the
array.
Example 2
Often, you need to return two separate values from a method. You can do this
easily with KeyValuePair. You must specify the exact type in the return value,
and then return the new KeyValuePair in the method body.
Tip:This is clearer than a two-element
array.
Consider out or ref parameters instead.
Program that returns two values: C#using System;
using System.Collections.Generic;class Program
{
static void Main()
{
Console.WriteLine(GetNames());
}static KeyValuePair<string, string> GetNames()
{
// Gets collection of first and last name.
string firstName = "William";
string lastName = "Gates";
return new KeyValuePair<string, string>(firstName, lastName);
}
}Output
[William, Gates]
Error
When using KeyValuePair in your program, you will likely get this error at
some point. The C# compiler doesn‘t allow you to assign the Key and Value
properties. This must be assigned in the constructor.
Error:Property or indexer ‘System.Collections.Generic.KeyValuePair...Key‘
cannot be assigned to--it is read-only.
Dictionary loop
Probably the most popular usage of KeyValuePair is in a loop over a
Dictionary. The Dictionary collection in C# has an enumerator that returns each
key and value in a KeyValuePair, one at a time. Examples are available.
Also:An improved syntax could be to use the var
keyword with the foreach loop over your Dictionary. This shortens the
syntax.
Sort
How can you sort a collection of KeyValuePair instances? You can implement a
custom sorting Comparison method. We use the delegate method syntax. The linked
tutorial contains information on this approach.
Also, you may use KeyValuePair in a List to create two
parallel Lists. These are easily sorted, keeping both values together. This site
has an example of an accurate shuffle algorithm with KeyValuePair and List.
Implementation
You should know the basic layout of the KeyValuePair struct. Here, we see the
internal code. The KeyValuePair has two private fields, and two public
properties that retrieve the values of those fields.
Implementation of KeyValuePair: C#[Serializable, StructLayout(LayoutKind.Sequential)]
public struct KeyValuePair<TKey, TValue>
{
private TKey key;
private TValue value;
public KeyValuePair(TKey key, TValue value);
public TKey Key { get; }
public TValue Value { get; }
public override string ToString();
}
ToString
The ToString method is useful. When you want to display the values, simply
call ToString or pass the KeyValuePair to Console.Write or Console.WriteLine.
This will implicitly call ToString. Internally, ToString uses a
StringBuilder.
Performance
Is there any advantage to using custom structs instead of KeyValuePair
generic types? Conceptually, the two approaches should be precisely equivalent
in functionality, but there are some differences in performance.
KeyValuePair performance
KeyValuePair influenced how the method was inlined.Method that uses normal struct: 0.32 ns
Method that uses KeyValuePair: 4.35 ns
Next, we figure out what we are comparing. It is always
possible to use custom structs with two fields instead of a KeyValuePair with
those types. My question was whether this is ever worthwhile doing.
Version 1struct CustomPair
{
public int Key;
public string Value;
}Version 2
KeyValuePair<int, string>
Next, we look at a benchmark that compares the two
structs. You would think that the .NET Framework would compile the two methods
in the exactly same way, but I found the methods are inlined in different
ways.
Program that tests KeyValuePair performanceusing System;
using System.Collections.Generic;
using System.Diagnostics;struct CustomPair
{
public int Key;
public string Value;
}class Program
{
const int _max = 300000000;
static void Main()
{
CustomPair p1;
p1.Key = 4;
p1.Value = "perls";
Method(p1);KeyValuePair<int, string> p2 = new KeyValuePair<int, string>(4, "perls");
Method(p2);for (int a = 0; a < 5; a++)
{
var s1 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
Method(p1);
Method(p1);
}
s1.Stop();
var s2 = Stopwatch.StartNew();
for (int i = 0; i < _max; i++)
{
Method(p2);
Method(p2);
}
s2.Stop();Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) /
_max).ToString("0.00 ns"));
Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) /
_max).ToString("0.00 ns"));
}
Console.Read();
}static int Method(CustomPair pair)
{
return pair.Key + pair.Value.Length;
}static int Method(KeyValuePair<int, string> pair)
{
return pair.Key + pair.Value.Length;
}
}Result
0.32 ns
4.35 ns
0.32 ns
4.34 ns
0.32 ns
4.36 ns
0.32 ns
4.35 ns
0.32 ns
4.36 ns
I looked inside the two Method implementations in the
IL Disassembler tool. They have the same code size. But in the KeyValuePair
version, the call instruction is used instead of ldfld because KeyValuePair uses
properties.
After C# compilation, the program is JIT-compiled
during runtime. The behavior of the inliner is sometimes hard to determine.
Extra members that need inlining sometimes influence the inliner and end up
reducing performance.
Tip:It is possible to improve performance by
replacing a KeyValuePair with a regular struct.
Discussion
In some contexts—such as internal method code—using KeyValuePair is
convenient and simple. But using a class or struct you define yourself can
definitely enhance the object-orientation of your program.
Therefore:I suggest you prefer classes when the usage
is not trivial. This improves object-oriented design.
ClassObject-Oriented
Programming
Tuple. Another option now available in the .NET
Framework is the Tuple type. You can have a two-element Tuple. A Tuple is a
class, not a struct. It can also have many more items in it.
Summary
We saw examples of using KeyValuePair in the C# language, and also looked
into its internals in the .NET Framework. Lists and Dictionaries are ideal
companions for KeyValuePairs. We returned the collection from methods.
KeyValuePair C#,布布扣,bubuko.com