I know IEnumerable.ToList() is supposed to create a new List, but with the items pointing to the same original items in the IEnumerable, as discussed at ToList()-- Does it Create a New List?
However, I'm getting some strange behavior with my code using VS 2012; WPF; and .NET 4.0. It started when IEnumerable.SequenceEquals() seemed not to work as I expected. I dug around with my QuickWatch dialog, and, unbelievably, the following statement evaluates to false:
this.Items.First () == this.Items.ToList ()[ 0 ]
I even tried:
this.Items.ToList ().IndexOf(this.Items.First ())
which evaluated to -1.
Items
is declared as a property on a WPF custom control, like so:
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 is simply a class generated by the XSD tool, with the following declaration:
//
// 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 {
This are the methods on a factory class that create the UserLayoutType Items in the first place:
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 );
}
}
Anybody have any idea what is happening? See image below:
The main, probable, cause for why you're seeing new objects from this is that the IEnumerable<T>
is wrapping a generator, and not a materialized collection.
Here's a simple LINQPad program to demonstrate:
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();
}
This will print False
.
It will do this because the act of enumerating over the collection (.ToList()
in this case) will execute the deferred LINQ query, and since we're enumerating the collection twice, we execute it twice, producing different instances with the same values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With