To exemplify my comment, look at this example:
public void RunTest()
{
Test t = new Stackoverflow.Form1.Test();
Console.WriteLine(t.Values.First());
System.Threading.Thread.Sleep(1000);
Console.WriteLine(t.Values.First());
System.Threading.Thread.Sleep(1000);
Console.WriteLine(t.Values.First());
Console.WriteLine("------");
Console.WriteLine(t.Values2.First());
System.Threading.Thread.Sleep(1000);
Console.WriteLine(t.Values2.First());
System.Threading.Thread.Sleep(1000);
Console.WriteLine(t.Values2.First());
Console.WriteLine("------");
Console.WriteLine(t.Values3.First());
System.Threading.Thread.Sleep(1000);
Console.WriteLine(t.Values3.First());
System.Threading.Thread.Sleep(1000);
Console.WriteLine(t.Values3.First());
}
public class Test
{
public IEnumerable<string> Values { get; set; } = GetValues();
public static IEnumerable<string> GetValues()
{
List<string> results = new List<string>();
for (int i = 0; i < 10; ++i)
{
yield return DateTime.UtcNow.AddMinutes(i).ToString();
}
}
public IEnumerable<string> Values2 { get; set; } = GetValues2();
public static IEnumerable<string> GetValues2()
{
return GetValues().ToList();
}
public IEnumerable<string> Values3 { get; set; } = GetValues().ToList();
}
The output from this is:
19/04/2017 12:24:25
19/04/2017 12:24:26
19/04/2017 12:24:27
------
19/04/2017 12:24:25
19/04/2017 12:24:25
19/04/2017 12:24:25
------
19/04/2017 12:24:25
19/04/2017 12:24:25
19/04/2017 12:24:25
Values: As you can see, the IEnumerable<> from the method using yield will be evaluated each time you call it.
Values2: The method returns a List. Since List implements IEmnumerable, you're still just returning the concrete instance of List (albeit presented as its IEnumerable interface) and thus it only gets evaluated once.
Values3: We've basically moved the .ToList() outside of the GetValues2() method and just implemented it directly on the property. The result here is the same as Values2, for basically the same reason.
When you return a concrete object that implements IEnumerable, it will be evaluated once, but watch out for the first example.
And remember folks, Linq is a view. if the underlying data changes, so does what's returned from your Linq expression.
Re the garbage collection question: Objects that are referenced by an active object will not be garbage collected.