从列表返回一个匹配>
我目前有一个类,它使用KeyValuePair
和List
以Key = track,Value = artist的格式存储轨道集合。从列表返回一个匹配<KeyValuePair <string,string >>
我试图提供一种搜索特定曲目的方法,如果有任何匹配,则返回整个匹配的CD。
这是迄今为止我尝试:
public CompilationCD FindTrackInComCD(string track)
{
CompilationCD temp = new CompilationCD();
List<CD> tempComCols = _cdCollection.FindAll(delegate(CD cd)
{ return cd.GetType() == temp.GetType(); });
foreach (KeyValuePair<string, string> comCD in tempComCols)
{
if (comCD.Key.Contains(track))
{
return comCD;
}
}
throw new ArgumentException("No matches found");
}
我的CD型CD(List<CD>
)的集合,因此,我通过比较临时列表创建此时,相应类型的新List<>
。
编译时我收到以下错误:
Cannot convert type 'CDCollection.CD' to System.Collections.Generic.KeyValuePair<string,string>'
Cannot implicitly convert type 'System.Collections.Generic.KeyValuePair<string,string>'
(CDCollection是我的项目命名空间和CD/CompilationCD是类)
对不起,这似乎像一个类似的问题,一个我已经以前问过。我试图使用之前给出的方法,但我有点难过;我经常没有使用List<>
或KeyValuePair
。
这是CD类:
using System;
System.Collections中使用; using System.Collections.Generic;使用System.Linq的 ; using System.Text;
命名空间CDCollection { 公共类CD { #地区字段 私人只读字符串_artist; private readonly string _album; private List _track = new List(); #endregion
#region Constructors
public CD()
{
_artist = "";
_album = "";
_track = null;
}
public CD(string albumName)
{
_album = albumName;
}
public CD(string artistName, string albumName)
{
_artist = artistName;
_album = albumName;
}
#endregion
#region Properties
/// <summary>
/// Get/Set Artist Name
/// </summary>
public virtual string Artist
{
get
{
return _artist;
}
set
{
value = _artist;
}
}
/// <summary>
/// Get/Set Album
/// </summary>
public string Album
{
get
{
return _album;
}
set
{
value = _album;
}
}
/// <summary>
/// Get/Set Track Name
/// </summary>
public virtual List<string> Track
{
get
{
return _track;
}
set
{
value = _track;
}
}
#endregion
#region ToString()
/// <summary>
/// Custom ToString() Method
/// </summary>
/// <returns></returns>
public override string ToString()
{
//Create new StringBuilder object
StringBuilder sb = new StringBuilder();
sb.Append("Artist Name");
//Display error if Artist is not available
if (_artist == null || _artist == "")
{
sb.Append("\nNo Artist Entered");
}
else
{
sb.Append("\n" + this._artist);
}
sb.Append("\n");
sb.Append("\nAlbum Name");
//Display error if Album is not available
if (_album == null || _album == "")
{
sb.Append("\nNo Album Entered");
}
else
{
sb.Append("\n" + this._album);
}
sb.Append("\n");
sb.Append("\nTrack Name");
sb.Append("\n");
//Iterate through all tracks stored in list
foreach (string trackName in _track)
{
//Print each artist
sb.Append("\n" + trackName);
}
sb.Append("\nEnd of CD Record.........");
return sb.ToString();
}
#endregion
}
}
这是CompilationCD类:
using System;
使用System.Collections.Generic;使用System.Linq的 ; using System.Text;
命名空间CDCollection { 公共类CompilationCD:CD { #地区字段
private readonly string _artist;
private readonly string _album;
private List<KeyValuePair<string,string>> _tracks = new List<KeyValuePair<string,string>>();
//List<KeyValuePair> Reference.
//http://msdn.microsoft.com/en-us/library/6sh2ey19(VS.85).aspx
#endregion
#region Constructors
public CompilationCD()
{
_album = "";
_artist = "Various Artists";
}
public CompilationCD(string albumName):base(albumName)
{
_album = albumName;
_artist = "Various Artists";
}
#endregion
public void AddTracks(string track, string artist)
{
_tracks.Add(new KeyValuePair<string, string>(track, artist));
}
#region Properties
public override string Artist
{
get
{
return this._artist;
}
}
public new List<KeyValuePair<string,string>> Track
{
get
{
return _tracks;
}
set
{
_tracks = value;
}
}
#endregion
#region ToString()
//TEST
public override string ToString()
{
//Create new StringBuilder object
StringBuilder sb = new StringBuilder();
sb.Append("Artist Name");
//Display error if Artist is not available
if (_artist == null || _artist == "")
{
sb.Append("\nNo Artist Entered");
}
else
{
sb.Append("\n" + this._artist);
}
sb.Append("\n");
sb.Append("\nAlbum Name");
//Display error if Album is not available
if (base.Album == null || base.Album == "")
{
sb.Append("\nNo Album Entered");
}
else
{
sb.Append("\n" + base.Album);
}
sb.Append("\n");
sb.Append("\nTrack Name");
sb.Append("\n");
////Iterate through all tracks stored in list
//foreach (string trackName in base.Track)
//{
// //Print each artist
// sb.Append("\n" + trackName);
//}
for(int i = 0; i <= _tracks.Count; i++)
{
string track = _tracks[i].Key;
string artist = _tracks[i].Value;
sb.Append("\nTrack");
sb.Append(track);
sb.Append("\nArtist");
sb.Append(artist);
}
sb.Append("\nEnd of Compilation CD Record.........");
return sb.ToString();
}
#endregion
}
}
我有严格的规定,这意味着我必须从CD继承创建我CompilationCD以及因为使用列表>我的曲目集合,它需要同时拥有曲目和艺术家。疯狂我知道=/
此外,我必须存储CD类型列表中的所有类型的CD(列表)。
问题出在您的foreach
循环中。 tempComCols
是List<CD>
,但是comCD
是KeyValuePair<string, string>
。所以,你的循环会导致无效的类型转换。
不幸的是,由于我们不知道CD
类(接口?)是什么样的,我无法就其属性提出修正建议。
编辑:以下也许是一个更好的版本的方法(虽然,我没有正确调试吧):
public CompilationCD FindTrackInComCD(string track)
{
CompilationCD temp = new CompilationCD();
temp = _cdCollection.Where(cd => cd is CompilationCD)
.Cast<CompilationCD>()
.Where(com_cd => com_cd.Tracks.ContainsKey(track))
.FirstOrDefault();
if (temp != null)
return temp;
else throw new ArgumentException("No matches found");
}
你不能投了CompilationCD
到KeyValuePair<string, string>
,所以我们直接使用CompilationCD
类。我们可以将搜索轨道列表的责任移交给System.Linq
提供的IEnumerable<T>
扩展方法,这使得此方法非常简单。
我已经添加了CD和CompilationCD的类=] – 2009-11-25 13:05:08
您使用的是哪个版本的.Net框架?根据LINQ是否可用,“标准”习语存在差异。 – Dathan 2009-11-25 17:12:15
我正在使用.Net 3.5 – 2009-11-28 22:56:22
为什么不使用字典?它们是关键值对的列表,但通过密钥提供了方便的访问。
当然,我不相信我没有想到这一点。 谢谢! – 2009-11-24 22:49:38
尝试实施字典后,事实证明它有可能会破坏太多。 – 2009-11-24 23:01:20
你是什么意思,“打破”?谨慎阐述? – McKay 2009-11-24 23:13:10
这是因为tempComCols
将返回CD
而不是KeyValuePair<string, string>
您List
不含KeyValuePairs
,所以你不能循环通过它,如果它没有。尝试是这样的:
foreach (CD comCD in tempComCols)
{
if (comCD.MyKeyValueProp.Key.Contains(track))
{
return comCD;
}
}
但作为麦凯说,如果你的CD
类做什么,但封装一个KeyValuePair
,一个Dictionary
就好办多了。
tempComCols是CD
项目清单:List<CD> tempComCols ...
,你想遍历的东西,是IEnumerable类型:foreach (KeyValuePair<string, string> comCD in tempComCols)
您枚举List<CD>
并分配到KeyValuePair<string, string>
。
您可以重写C#3使用LINQ你这样的方法:
public CompilationCD FindTrackInComCD(string track) {
return _cdCollection.OfType<CompilationCD>().FirstOrDefault(cd => cd.Name.Contains(track, StringComparison.CurrentCultureIgnoreCase));
}
顺便说一句,你可以通过编写typeof(CompilationCD)
得到CompilationCD
的System.Type
对象;你不需要拨打GetType()
。
-
你可以使用:
{cd is CompilationCD};
代替
{ return cd.GetType() == temp.GetType(); });
-
,如果我理解正确的CD是某种解释的,你可以重写功能:
public CompilationCD FindTrackInComCD(string track) { return (CompilationCD)_cdCollection.Find(delegate(CD cd) { return (cd is CompilationCD) && (cd.Contains(track))}); }
您应该考虑使用运算符'is'而不是比较'GetType()'的返回值。它既快又短,并且在扩展性方面表现更好(例如,如果你以后从'CompilationCD'派生出一些类)。 – 2009-11-24 23:04:35