奇怪的是,IEnumerable.ToList()创建了全新的对象

时间:2013-08-26 03:05:50

标签: c# list .net-4.0 ienumerable

我知道IEnumerable.ToList()应该创建一个新的List,但是项目指向IEnumerable中的相同原始项目,如ToList()-- Does it Create a New List?

中所讨论的

然而,我在使用VS 2012的代码时遇到了一些奇怪的行为; WPF;和.NET 4.0。它开始于IEnumerable.SequenceEquals()似乎没有像我预期的那样工作。我在我的QuickWatch对话框中进行了挖掘,令人难以置信的是,以下语句的计算结果为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

1 个答案:

答案 0 :(得分: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查询,并且因为我们枚举集合两次,所以我们执行它两次,产生不同的实例具有相同的值。