2009-11-24 4 views
3

В настоящее время у меня есть класс, который использует KeyValuePair с List для хранения коллекции треков в формате Key = track, Value = artist.Возврат соответствия из списка <KeyValuePair <строка, строка >>

Я пытаюсь обеспечить способ поиска определенного трека, и если есть какие-либо соответствия, верните весь соответствующий компакт-диск.

Это моя попытка до сих пор:

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 (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 очень часто.

Это компакт-диск Класс:

using System; 

использованием System.Collections; с использованием System.Collections.Generic; с использованием System.Linq; с использованием System.Text;

имен CDCollection { класс CD общественного { #region Поля частной чтения строки _artist; приватная строка readonly _album; приватный список _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 { общественного класса 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 
} 

}

У меня есть строгие правила, которые означают, что я должен наследоваться от компакт-диска, чтобы создать свой CompilationCD, а также как использование списка> для моей коллекции треков, он должен содержать как дорожку, так и исполнителя. Crazy i know =/

Кроме того, я должен хранить ВСЕ типы CD в списке типа CD (List).

+1

Вы должны использовать оператор 'is' вместо сравнения возвращаемых значений' GetType() '. Это быстрее, короче и лучше работает с расширяемостью (например,если позже вывести некоторый класс из 'CompilationCD'). –

ответ

2

Проблема в вашей петле foreach. tempComCols - List<CD>, но comCD - это KeyValuePair<string, string>. Таким образом, ваш цикл приводит к неверному преобразованию типа.

К сожалению, поскольку мы не знаем, что класс CD (интерфейс?) Выглядит, я не могу предложить исправление с точки зрения его свойств.

EDIT: Ниже возможно лучший вариант вашего метода (хотя, я не отлажено правильно):

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. Мы можем передать ответственность за поиск в списке дорожек методам extenion IEnumerable<T>, предоставленным System.Linq, что делает этот метод очень простым.

+0

Я добавил классы для компакт-диска и компиляцииCD =] –

+0

Какую версию .NET Framework вы используете? Существуют различия в «стандартной» идиоме на основе доступности LINQ или нет. – Dathan

+0

Я использую .Net 3.5 –

5

Почему бы не использовать словарь?Они представляют собой пары ключевых значений, но обеспечивают легкий доступ через ключ.

+0

Конечно, я не могу поверить, что не думал об этом. Спасибо! –

+0

После попытки реализовать словарь, оказывается, есть шанс, что он слишком сильно сломается. –

+0

Что значит «ломать»? Поразмыслить? – McKay

0

это потому, что tempComCols вернется CD и не KeyValuePair<string, string>

0

Ваш List не содержит KeyValuePairs, так что вы не можете цикл через него, как будто это сделал. Попробуйте что-то вроде этого:

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

Но, как сказал Маккей, если ваш CD класс ничего не делает, но инкапсулировать KeyValuePair, Dictionary было бы гораздо проще.

0

tempComCols является список CD пунктов: List<CD> tempComCols ... и вы хотите перебрать что-то типа IEnumerable: foreach (KeyValuePair<string, string> comCD in tempComCols)

0

Вы перечислив List<CD> и присваивание KeyValuePair<string, string>.

Вы можете переписать метод с использованием LINQ в C# 3, как это:

public CompilationCD FindTrackInComCD(string track) { 
    return _cdCollection.OfType<CompilationCD>().FirstOrDefault(cd => cd.Name.Contains(track, StringComparison.CurrentCultureIgnoreCase)); 
} 

Кстати, вы можете получить System.Type объект для CompilationCD написав typeof(CompilationCD); вам не нужно звонить 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))}); 
    }