Returning a match from a List<KeyValuePair<string,string>>

21,675

Solution 1

The problem is in your foreach loop. tempComCols is a List<CD>, but comCD is a KeyValuePair<string, string>. So, your loop results in an invalid type conversion.

Unfortunately, since we don't know what the CD class (interface?) looks like, I can't suggest a fix in terms of its properties.

EDIT: The following is perhaps a better version of your method (though, I haven't debugged it correctly):

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");
}

You can't cast a CompilationCD to a KeyValuePair<string, string>, so we just use the CompilationCD class directly. We can pass off the responsibility for searching the track list to the IEnumerable<T> extenion methods provided by System.Linq, which makes this method very easy.

Solution 2

Why not use a dictionary? They are a list of key value pairs, but provide easy access via the key.

Share:
21,675
Jamie Keeling
Author by

Jamie Keeling

SOreadytohelp

Updated on November 30, 2020

Comments

  • Jamie Keeling
    Jamie Keeling over 3 years

    I currently have a class that uses the KeyValuePair with List to store a collection of tracks in the format of Key = track, Value = artist.

    I'm trying to provide a way of searching for a particular track and if there are any matches then return the entire matching CD.

    This is my attempt so far:

    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");
    }
    

    I have a collection of Cd's of type CD (List<CD>) therefore I create a new List<> of the appropiate type by comparing it to the temp List.

    When compiling I get the following errors:

    Cannot convert type 'CDCollection.CD' to System.Collections.Generic.KeyValuePair<string,string>'
    
    Cannot implicitly convert type 'System.Collections.Generic.KeyValuePair<string,string>'
    

    (CDCollection is my project namespace and CD/CompilationCD are the classes)

    Sorry for this seeming like a similar question to one I've previously asked. I tried to use the methods I was given before but I'm a bit stumped; I've not used List<> or KeyValuePair very often.

    This is the CD Class:

    using System;
    

    using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text;

    namespace CDCollection { public class CD { #region Fields 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
    }
    

    }

    This is the CompilationCD class:

    using System;
    

    using System.Collections.Generic; using System.Linq; using System.Text;

    namespace CDCollection { public class CompilationCD : CD { #region Fields

        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
    }
    

    }

    I have strict rules that mean i have to inherit from CD to create my CompilationCD as well as using a List> for my track collection, it needs to hold both a track and artist. Crazy i know =/

    Furthermore i must store ALL types of cd in a list of type CD ( List ).