返回LINQ大全首页
ToDictionary()可以用序列(例如数组和list)快速创建Dictionary。
平时我们可能习惯用Foreach把List或数组中的内容转换为Dictionary,代码如下。
using System.Linq;
using System.Collections;
using System.Collections.Generic;
public static class Program
{
private class Parameter
{
public int ID { get; set; }
public int Age { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format( "ID:{0}, Age:{1}, Name:{2}", ID, Age, Name );
}
}
static void Main( string[] args )
{
Parameter[] parameters = new Parameter[]
{
new Parameter() { ID = 0, Age = 52, Name = "正一郎" },
new Parameter() { ID = 8, Age = 28, Name = "清次郎" },
new Parameter() { ID = 3, Age = 20, Name = "誠三郎" },
new Parameter() { ID = 4, Age = 18, Name = "征史郎" },
};
Dictionary dictionary = new Dictionary();
foreach( var parameter in parameters )
{
dictionary.Add( parameter.ID, parameter );
}
System.Console.WriteLine( "parameters:{0}", parameters.Text() );
System.Console.WriteLine( "dictionary:{0}", dictionary.Text() );
System.Console.ReadKey();
}
public static string Text( this IEnumerable i_source )
{
string text = string.Empty;
foreach( var value in i_source )
{
text += string.Format( "[{0}], ", value );
}
return text;
}
}
parameters:[ID:0, Age:52, Name:正一郎], [ID:8, Age:28, Name:清次郎], [ID:3, Age:
20, Name:誠三郎], [ID:4, Age:18, Name:征史郎],
dictionary:0, ID:0, Age:52, Name:正一郎, 8, ID:8, Age:28, Name:清次郎, [
[3, ID:3, Age:20, Name:誠三郎]], 4, ID:4, Age:18, Name:征史郎,
完成了。这是可行的,但LINQ的ToDictionary()可用于简化代码。
MSDN
要使用ToDictionary(),只需从数组或List中调用它,并描述获取key属性作为参数的过程。value默认为当前的数组或List。 以下示例描述了使用lambda表达式获取key属性的过程。
using System.Linq;
using System.Collections;
using System.Collections.Generic;
public static class Program
{
private class Parameter
{
public int ID { get; set; }
public int Age { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format( "ID:{0}, Age:{1}, Name:{2}", ID, Age, Name );
}
}
static void Main( string[] args )
{
Parameter[] parameters = new Parameter[]
{
new Parameter() { ID = 0, Age = 52, Name = "正一郎" },
new Parameter() { ID = 8, Age = 28, Name = "清次郎" },
new Parameter() { ID = 3, Age = 20, Name = "誠三郎" },
new Parameter() { ID = 4, Age = 18, Name = "征史郎" },
};
Dictionary dictionary = parameters.ToDictionary( value => value.ID );
System.Console.WriteLine( "parameters:{0}", parameters.Text() );
System.Console.WriteLine( "dictionary:{0}", dictionary.Text() );
System.Console.ReadKey();
}
public static string Text( this IEnumerable i_source )
{
string text = string.Empty;
foreach( var value in i_source )
{
text += string.Format( "[{0}], ", value );
}
return text;
}
}
parameters:[ID:0, Age:52, Name:正一郎], [ID:8, Age:28, Name:清次郎], [ID:3, Age:
20, Name:誠三郎], [ID:4, Age:18, Name:征史郎],
dictionary:0, ID:0, Age:52, Name:正一郎, 8, ID:8, Age:28, Name:清次郎, [
[3, ID:3, Age:20, Name:誠三郎]], 4, ID:4, Age:18, Name:征史郎,
前面我们value直接使用的是List或数组里的内容,我们也可以通过传入第二个参数自定义value的值。 下面是通过lambda表达式传入value值的例子。
using System.Linq;
using System.Collections;
using System.Collections.Generic;
public static class Program
{
private class Parameter
{
public int ID { get; set; }
public int Age { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format( "ID:{0}, Age:{1}, Name:{2}", ID, Age, Name );
}
}
static void Main( string[] args )
{
Parameter[] parameters = new Parameter[]
{
new Parameter() { ID = 0, Age = 52, Name = "正一郎" },
new Parameter() { ID = 8, Age = 28, Name = "清次郎" },
new Parameter() { ID = 3, Age = 20, Name = "誠三郎" },
new Parameter() { ID = 4, Age = 18, Name = "征史郎" },
};
Dictionary dictionary = parameters.ToDictionary( value => value.ID, value => value.Name );
System.Console.WriteLine( "parameters:{0}", parameters.Text() );
System.Console.WriteLine( "dictionary:{0}", dictionary.Text() );
System.Console.ReadKey();
}
public static string Text( this IEnumerable i_source )
{
string text = string.Empty;
foreach( var value in i_source )
{
text += string.Format( "[{0}], ", value );
}
return text;
}
}
parameters:[ID:0, Age:52, Name:正一郎], [ID:8, Age:28, Name:清次郎], [ID:3, Age:
20, Name:誠三郎], [ID:4, Age:18, Name:征史郎],
dictionary:0, 正一郎, 8, 清次郎, 3, 誠三郎, 4, 征史郎,
所以说当仅有一个参数时传入的是key,value默认为当前转换的List或数组的值。(key) 两个参数时第一个为key,第二个为value。(key,value)
当我们传入的键有重复的会怎么样呢?
using System.Linq;
using System.Collections;
using System.Collections.Generic;
public static class Program
{
private class Parameter
{
public int ID { get; set; }
public int Age { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format( "ID:{0}, Age:{1}, Name:{2}", ID, Age, Name );
}
}
static void Main( string[] args )
{
Parameter[] parameters = new Parameter[]
{
new Parameter() { ID = 0, Age = 52, Name = "正一郎" },
new Parameter() { ID = 8, Age = 28, Name = "清次郎" },
new Parameter() { ID = 4, Age = 20, Name = "誠三郎" },
new Parameter() { ID = 4, Age = 18, Name = "征史郎" },
};
Dictionary dictionary = null;
try
{
dictionary = parameters.ToDictionary( value => value.ID );
}
catch( System.Exception i_exception )
{
System.Console.WriteLine( "{0}", i_exception );
System.Console.ReadKey();
return;
}
System.Console.WriteLine( "parameters:{0}", parameters.Text() );
System.Console.WriteLine( "dictionary:{0}", dictionary.Text() );
System.Console.ReadKey();
}
public static string Text( this IEnumerable i_source )
{
string text = string.Empty;
foreach( var value in i_source )
{
text += string.Format( "[{0}], ", value );
}
return text;
}
}
System.ArgumentException: 包含相同键的项已添加。
注意如果传入相同key值会报错。
前面用的都是值类型作为key,下面尝试下用引用类型作为key。
using System.Linq;
using System.Collections;
using System.Collections.Generic;
public static class Program
{
private class KeyData
{
public int ID { get; set; }
public string Version { get; set; }
public override string ToString()
{
return string.Format( "{0}_{1}", ID, Version );
}
}
private class Parameter
{
public KeyData Key { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format( "Key:{0}, Name:{1}", Key, Name );
}
}
static void Main( string[] args )
{
Parameter[] parameters = new Parameter[]
{
new Parameter() { Key = new KeyData() { ID = 0, Version = "A" }, Name = "正一郎" },
new Parameter() { Key = new KeyData() { ID = 0, Version = "B" }, Name = "清次郎" },
new Parameter() { Key = new KeyData() { ID = 2, Version = "C" }, Name = "誠三郎" },
new Parameter() { Key = new KeyData() { ID = 2, Version = "C" }, Name = "征史郎" },
};
Dictionary dictionary = null;
try
{
dictionary = parameters.ToDictionary( value => value.Key );
}
catch( System.Exception i_exception )
{
System.Console.WriteLine( "{0}", i_exception );
System.Console.ReadKey();
return;
}
System.Console.WriteLine( "parameters:{0}", parameters.Text() );
System.Console.WriteLine( "dictionary:{0}", dictionary.Text() );
try
{
Parameter result = dictionary[ new KeyData() { ID = 2, Version = "C" } ];
System.Console.WriteLine( "result:{0}", result );
}
catch( System.Exception i_exception )
{
System.Console.WriteLine( "{0}", i_exception );
System.Console.ReadKey();
return;
}
System.Console.ReadKey();
}
public static string Text( this IEnumerable i_source )
{
string text = string.Empty;
foreach( var value in i_source )
{
text += string.Format( "[{0}], ", value );
}
return text;
}
}
parameters:[Key:0_A, Name:正一郎], [Key:0_B, Name:清次郎], [Key:2_C, Name:誠三郎
], [Key:2_C, Name:征史郎],
dictionary:0_A, Key:0_A, Name:正一郎, 0_B, Key:0_B, Name:清次郎, [[2_C,
Key:2_C, Name:誠三郎]], 2_C, Key:2_C, Name:征史郎,
System.Collections.Generic.KeyNotFoundException: 指定的key在中不存在。
结果是我们可以使用引用类型作为键,但是要注意的是取值是根据引用而不是内容,所以即使内容相同但是引用不同就不会报错。
下面使用相同引用作为键进行尝试。
using System.Linq;
using System.Collections;
using System.Collections.Generic;
public static class Program
{
private class KeyData
{
public int ID { get; set; }
public string Version { get; set; }
public override string ToString()
{
return string.Format( "{0}_{1}", ID, Version );
}
}
private class Parameter
{
public KeyData Key { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format( "Key:{0}, Name:{1}", Key, Name );
}
}
static void Main( string[] args )
{
KeyData keyA = new KeyData() { ID = 0, Version = "A" };
KeyData keyB = new KeyData() { ID = 0, Version = "B" };
KeyData keyC = new KeyData() { ID = 2, Version = "C" };
Parameter[] parameters = new Parameter[]
{
new Parameter() { Key = keyA, Name = "正一郎" },
new Parameter() { Key = keyB, Name = "清次郎" },
new Parameter() { Key = keyC, Name = "誠三郎" },
new Parameter() { Key = keyC, Name = "征史郎" },
};
Dictionary dictionary = null;
try
{
dictionary = parameters.ToDictionary( value => value.Key );
}
catch( System.Exception i_exception )
{
System.Console.WriteLine( "{0}", i_exception );
System.Console.ReadKey();
return;
}
System.Console.WriteLine( "parameters:{0}", parameters.Text() );
System.Console.WriteLine( "dictionary:{0}", dictionary.Text() );
System.Console.ReadKey();
}
public static string Text( this IEnumerable i_source )
{
string text = string.Empty;
foreach( var value in i_source )
{
text += string.Format( "[{0}], ", value );
}
return text;
}
}
System.ArgumentException: 相同键的项已添加。
结果会报错。如果删除重复的数据将可以正常运行。
using System.Linq;
using System.Collections;
using System.Collections.Generic;
public static class Program
{
private class KeyData
{
public int ID { get; set; }
public string Version { get; set; }
public override string ToString()
{
return string.Format( "{0}_{1}", ID, Version );
}
}
private class Parameter
{
public KeyData Key { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format( "Key:{0}, Name:{1}", Key, Name );
}
}
static void Main( string[] args )
{
KeyData keyA = new KeyData() { ID = 0, Version = "A" };
KeyData keyB = new KeyData() { ID = 0, Version = "B" };
KeyData keyC = new KeyData() { ID = 2, Version = "C" };
Parameter[] parameters = new Parameter[]
{
new Parameter() { Key = keyA, Name = "正一郎" },
new Parameter() { Key = keyB, Name = "清次郎" },
new Parameter() { Key = keyC, Name = "誠三郎" },
// new Parameter() { Key = keyC, Name = "征史郎" },
};
Dictionary dictionary = null;
try
{
dictionary = parameters.ToDictionary( value => value.Key );
}
catch( System.Exception i_exception )
{
System.Console.WriteLine( "{0}", i_exception );
System.Console.ReadKey();
return;
}
System.Console.WriteLine( "parameters:{0}", parameters.Text() );
System.Console.WriteLine( "dictionary:{0}", dictionary.Text() );
try
{
Parameter result = dictionary[ keyC ];
System.Console.WriteLine( "result:{0}", result );
}
catch( System.Exception i_exception )
{
System.Console.WriteLine( "{0}", i_exception );
System.Console.ReadKey();
return;
}
System.Console.ReadKey();
}
public static string Text( this IEnumerable i_source )
{
string text = string.Empty;
foreach( var value in i_source )
{
text += string.Format( "[{0}], ", value );
}
return text;
}
}
parameters:[Key:0_A, Name:正一郎], [Key:0_B, Name:清次郎], [Key:2_C, Name:誠三郎
],
dictionary:0_A, Key:0_A, Name:正一郎, 0_B, Key:0_B, Name:清次郎, [[2_C,
Key:2_C, Name:誠三郎]],
result:Key:2_C, Name:誠三郎
我们了解了将引用类型用作键时的行为,但是也可以让类中属性的值进行比较。 在这种情况下需要使用ToDictionary()的重载。 通过传递继承自IEqualityComparer
的比较类,可以执行自定义的key比较处理。
using System.Linq;
using System.Collections;
using System.Collections.Generic;
public static class Program
{
private class KeyData
{
public int ID { get; set; }
public string Version { get; set; }
public override string ToString()
{
return string.Format( "{0}_{1}", ID, Version );
}
}
private class KeyDataComparer : IEqualityComparer
{
public bool Equals( KeyData i_lhs, KeyData i_rhs )
{
if( i_lhs.ID == i_rhs.ID &&
i_lhs.Version == i_rhs.Version )
{
return true;
}
return false;
}
public int GetHashCode( KeyData i_obj )
{
return i_obj.ID ^ i_obj.Version.GetHashCode();
}
}
private class Parameter
{
public KeyData Key { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format( "Key:{0}, Name:{1}", Key, Name );
}
}
static void Main( string[] args )
{
Parameter[] parameters = new Parameter[]
{
new Parameter() { Key = new KeyData() { ID = 0, Version = "A" }, Name = "正一郎" },
new Parameter() { Key = new KeyData() { ID = 0, Version = "B" }, Name = "清次郎" },
new Parameter() { Key = new KeyData() { ID = 2, Version = "C" }, Name = "誠三郎" },
new Parameter() { Key = new KeyData() { ID = 2, Version = "C" }, Name = "征史郎" },
};
Dictionary dictionary = null;
try
{
KeyDataComparer comparer = new KeyDataComparer();
dictionary = parameters.ToDictionary( value => value.Key, comparer );
}
catch( System.Exception i_exception )
{
System.Console.WriteLine( "{0}", i_exception );
System.Console.ReadKey();
return;
}
System.Console.WriteLine( "parameters:{0}", parameters.Text() );
System.Console.WriteLine( "dictionary:{0}", dictionary.Text() );
System.Console.ReadKey();
}
public static string Text( this IEnumerable i_source )
{
string text = string.Empty;
foreach( var value in i_source )
{
text += string.Format( "[{0}], ", value );
}
return text;
}
}
System.ArgumentException: 已经存在相同的键。
ToDictionary()
这时发生了异常。 这里的引用并不相同,但是有两个key的内容是相同的,报错说明方法起了效果。
using System.Linq;
using System.Collections;
using System.Collections.Generic;
public static class Program
{
private class KeyData
{
public int ID { get; set; }
public string Version { get; set; }
public override string ToString()
{
return string.Format( "{0}_{1}", ID, Version );
}
}
private class KeyDataComparer : IEqualityComparer
{
public bool Equals( KeyData i_lhs, KeyData i_rhs )
{
if( i_lhs.ID == i_rhs.ID &&
i_lhs.Version == i_rhs.Version )
{
return true;
}
return false;
}
public int GetHashCode( KeyData i_obj )
{
return i_obj.ID ^ i_obj.Version.GetHashCode();
}
}
private class Parameter
{
public KeyData Key { get; set; }
public string Name { get; set; }
public override string ToString()
{
return string.Format( "Key:{0}, Name:{1}", Key, Name );
}
}
static void Main( string[] args )
{
Parameter[] parameters = new Parameter[]
{
new Parameter() { Key = new KeyData() { ID = 0, Version = "A" }, Name = "正一郎" },
new Parameter() { Key = new KeyData() { ID = 0, Version = "B" }, Name = "清次郎" },
new Parameter() { Key = new KeyData() { ID = 2, Version = "C" }, Name = "誠三郎" },
new Parameter() { Key = new KeyData() { ID = 3, Version = "C" }, Name = "征史郎" },
};
Dictionary dictionary = null;
try
{
KeyDataComparer comparer = new KeyDataComparer();
dictionary = parameters.ToDictionary( value => value.Key, comparer );
}
catch( System.Exception i_exception )
{
System.Console.WriteLine( "{0}", i_exception );
System.Console.ReadKey();
return;
}
System.Console.WriteLine( "parameters:{0}", parameters.Text() );
System.Console.WriteLine( "dictionary:{0}", dictionary.Text() );
try
{
Parameter result = dictionary[ new KeyData() { ID = 2, Version = "C" } ];
System.Console.WriteLine( "result:{0}", result );
}
catch( System.Exception i_exception )
{
System.Console.WriteLine( "{0}", i_exception );
System.Console.ReadKey();
return;
}
System.Console.ReadKey();
}
public static string Text( this IEnumerable i_source )
{
string text = string.Empty;
foreach( var value in i_source )
{
text += string.Format( "[{0}], ", value );
}
return text;
}
}
parameters:[Key:0_A, Name:正一郎], [Key:0_B, Name:清次郎], [Key:2_C, Name:誠三郎
], [Key:3_C, Name:征史郎],
dictionary:0_A, Key:0_A, Name:正一郎, 0_B, Key:0_B, Name:清次郎, [[2_C,
Key:2_C, Name:誠三郎]], 3_C, Key:3_C, Name:征史郎,
result:Key:2_C, Name:誠三郎
即使将引用类型用作key,也可以用这种方法根据内容进行取值比较。