2013-08-26 78 views
9

我知道IEnumerable.ToList()應該創建一個新的列表,但指着IEnumerable的同一原始項目的項目,截至ToList()-- Does it Create a New List?奇怪,IEnumerable.ToList()創建全新的對象

討論

但是,我使用VS 2012獲得了一些奇怪的行爲; WPF;和.NET 4.0。它開始時IEnumerable.SequenceEquals()似乎沒有按預期工作。我與我的對話快速監視周圍挖,而且令人難以置信的,下面的語句計算結果爲false:

this.Items.First() == this.Items.ToList()[ 0 ] 

我甚至嘗試:

this.Items.ToList().IndexOf(this.Items.First()) 

其評價爲-1。

Items被聲明爲一個WPF自定義控件的屬性,像這樣:

public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register (
     "Items", 
     typeof (IEnumerable<UserLayoutType>), 
     typeof (UserLayoutSelectorControl), 
     new FrameworkPropertyMetadata (null, FrameworkPropertyMetadataOptions.AffectsRender, UserLayoutSelectorControl.PropertyChanged)); 


public IEnumerable<UserLayoutType> Items 
{ 
    get 
    { 
     return (IEnumerable<UserLayoutType>) this.GetValue (UserLayoutSelectorControl.ItemsProperty); 
    } 
    set 
    {  
     this.SetValue (UserLayoutSelectorControl.ItemsProperty, value);     
    } 
} 

UserLayoutType僅僅是由XSD工具生成的一類,具有以下聲明:

// 
// This source code was auto-generated by xsd, Version=4.0.30319.17929. 
// 
namespace MyAssays.UserLayoutCore.UserLayoutUtility { 
    using System.Xml.Serialization; 


    /// <remarks/> 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.17929")] 
    [System.SerializableAttribute()] 
    [System.Diagnostics.DebuggerStepThroughAttribute()] 
    [System.ComponentModel.DesignerCategoryAttribute("code")] 
    [System.Xml.Serialization.XmlRootAttribute("UserLayout", Namespace="", IsNullable=false)] 
    public partial class UserLayoutType { 

這是創建UserLayoutType項目的工廠類中的方法:

public static IEnumerable<UserLayoutType> CreateFromFolder (string folderPath) 
    { 
     if (String.IsNullOrEmpty(folderPath)) 
      throw new ArgumentNullException("folderPath", "Folder path must not be null"); 

     var userLayoutXmlFilePaths = Directory.GetFiles (folderPath).Where (filePath => filePath.EndsWith (".UserLayout.xml", StringComparison.InvariantCultureIgnoreCase)); 
     return userLayoutXmlFilePaths.Select(filePath => UserLayoutFactory.CreateFromFile(filePath)); 
    } 

    public static UserLayoutType CreateFromFile (string filePath) 
    { 
     using (var stream = new StreamReader (filePath)) 
     { 
      return (UserLayoutType) new XmlSerializer (typeof (UserLayoutType)).Deserialize (stream); 
     } 
    } 

有人知道發生了什麼嗎?如下圖所示: enter image description here

+0

嗨,請嘗試.Equals方法,即。 this.Items.First()。equals(this.Items.ToList()[0]) – user1778606

+0

聲明的項目是什麼?我認爲最好嘗試創建一段簡短的代碼,以顯示您正在討論的問題。然後在你的問題中發佈代碼。除此之外,您需要了解==和.Equals()之間的區別 – dcaswell

+0

「this.Items」的運行時類型是什麼? 'Equals'或'=='沒有覆蓋? – Blorgbeard

回答

7

您爲什麼看到新對象的主要原因可能是IEnumerable<T>包裝了一個生成器,而不是物化集合。

這裏有一個簡單LINQPad程序來演示:

void Main() 
{ 
    IEnumerable<string> collection = 
     from index in Enumerable.Range(1, 10) 
     select "Index=" + index; 

    var list1 = collection.ToList(); 
    var list2 = collection.ToList(); 

    ReferenceEquals(list1[0], list2[0]).Dump(); 
} 

這將打印False

它會這樣做是因爲在集合上枚舉的行爲(在這種情況下爲.ToList())將執行延遲LINQ查詢,並且由於我們兩次枚舉集合,我們執行兩次,生成具有相同值。