从List<KeyValuePair<string,string>>中返回匹配项

3

我目前有一个使用 KeyValuePairList 存储以键值对格式为 Key = track,Value = artist 的音轨集合的类。

我想提供一种查找特定音轨并返回整个匹配 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>'
是我的项目命名空间,和是类。 抱歉,这似乎是我之前问过的一个类似的问题。我尝试使用我之前得到的方法,但我有点困惑;我很少使用 >或。
这是类:
using System;

使用System.Collections; 使用System.Collections.Generic; 使用System.Linq; 使用System.Text;

命名空间CDCollection { public class CD { #region 字段 private readonly string _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; 使用 System.Text;

命名空间 CDCollection { public class CompilationCD : CD { #region 字段

    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,同时使用List>来存储我的曲目集合,它需要保存曲目和艺术家。很疯狂,我知道 =/

此外,我必须将所有类型的cd存储在类型为CD的列表中(List)。


1
你应该考虑使用运算符 is 而不是比较 GetType() 的返回值。这样做更快、更简短,而且与可扩展性更好(例如,如果以后从 CompilationCD 派生某个类)。 - Pavel Minaev
8个回答

5
为什么不使用字典?它们是一组键值对列表,但可以通过键轻松访问。

尝试实现字典后,发现有可能会出现过多的错误。 - Jamie Keeling
你说的“breaking”是什么意思?能详细解释一下吗? - McKay
我的程序是成对设计的,我的搭档已经做出了自己的贡献,但是如果不改变整个应用程序的大部分内容,就没有太多可以改变的余地了。 - Jamie Keeling
我认为字典是你最好的选择。你最好重构一下代码,把它们整理干净。 - McKay
好的,如果我将字典存储在List<>中,我该如何通过属性访问键和值? - Jamie Keeling

2
问题出在您的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的类 =] - Jamie Keeling
你正在使用哪个版本的 .Net 框架?基于 LINQ 是否可用,"standard" 习惯用语存在差异。 - Dathan

0

你的List不包含KeyValuePairs,所以你不能像遍历它一样循环。尝试像这样:

foreach (CD comCD in tempComCols)
{
    if (comCD.MyKeyValueProp.Key.Contains(track))
    {
        return comCD;
    }
}

但正如麦凯所说,如果你的CD类只是封装了一个KeyValuePair,那么使用Dictionary会更容易些。

0

您正在枚举一个 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)来获取CompilationCDSystem.Type对象;你不需要调用GetType()


0
  1. 你可以使用:

    {cd is CompilationCD};
    

    代替

    { return cd.GetType() == temp.GetType(); });
    
  2. 如果我理解正确,CD是某种字典,那么你可以重写函数如下:

    public CompilationCD FindTrackInComCD(string track)
    {
        return (CompilationCD)_cdCollection.Find(delegate(CD cd)
        { return (cd is CompilationCD) && (cd.Contains(track))});
    }
    

0

这是因为tempComCols将返回CD而不是KeyValuePair<string, string>


0

tempComCols 是 CD 项目的列表:List<CD> tempComCols ...,您想要迭代的是 IEnumerable 类型的某些内容:foreach (KeyValuePair<string, string> comCD in tempComCols)



网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接