为什么延迟加载 C# 中的数据在我需要之前加载?

Why data in Lazy Loading C# is loaded before I need it?

在一个网站上我读到:

Lady loading is the concept of delaying the loading of an object until we need this data. In other words, we load the object on demand, rather than unnecessarily loading data earlier.

我想尝试在我的简单控制台应用程序中使用延迟加载。

Student Class

 public class Students
    {
        public string Name { get; set; }
        public string Surname { get; set; }
        public string PESEL { get; set; }

        private Lazy<List<Students>> LazyStudents;
        

        public Students()
        {
           
        }

        public List<Students> StudentsProperty
        {
            get
            {
                if (LazyStudents == null)
                    LazyStudents = new Lazy<List<Students>>(() => LoadStudensList());
                return LazyStudents.Value;
            }
        }

        public List<Students> LoadStudensList()
        {
            List<Students> tempStudentsList = new List<Students>();
            tempStudentsList.Add(new Students() { Name = "Adam", Surname = "Wróbel", PESEL = "96120904999" });
            tempStudentsList.Add(new Students() { Name = "Edyta", Surname = "Urbańczyk", PESEL = "76354736458" });
            tempStudentsList.Add(new Students() { Name = "Gabriela", Surname = "Rydwańska", PESEL = "72637284923" });
            tempStudentsList.Add(new Students() { Name = "Dawid", Surname = "Rytel", PESEL = "62736482732" });

            return tempStudentsList;
        }
    }

ProgramMain()方法:

 class Program
    {
        static void Main(string[] args)
        {
            Students students = new Students();
            
            Console.WriteLine("Hello World!");
            foreach (var items in students.StudentsProperty)
            {
                    Console.WriteLine($"Imię: {items.Name}");
                    Console.WriteLine($"Nazwisko: {items.Surname}");
                    Console.WriteLine($"PESEL: {items.PESEL}");
                    Console.WriteLine("");
            }

            Console.WriteLine("Hello World!");
        }
    }

我想我使用延迟加载,当我创建 Students class StudentsProperty 的新对象(return 来自延迟列表的元素)仍然是空的。当我使用使用 StudentsProperty

的方法时,将向 LazyList 添加元素
 foreach (var items in students.StudentsProperty)
            {
                    Console.WriteLine($"Imię: {items.Name}");
                    Console.WriteLine($"Nazwisko: {items.Surname}");
                    Console.WriteLine($"PESEL: {items.PESEL}");
                    Console.WriteLine("");
            }

我在 foreach 循环之前添加断点,我看到 StudentsProperty 有元素:

我是否错误地实现了延迟加载,或者我理解有误?

Lazy.Value 是对懒惰进行评估的时间。

  LazyStudents = new Lazy<List<Students>>(() => LoadStudensList());
  return LazyStudents.Value;

没有任何意义。在第一行你说“在需要的时候评估”,第二行说“我现在需要它”。

通过空值检查,您已经自行完成了所有惰性求值。使用这个:

    private Lazy<List<Students>> LazyStudents = new Lazy<List<Students>>(() => LoadStudensList());

    public List<Students> StudentsProperty
    {
        get
        {
            return LazyStudents.Value;
        }
    }

或者这个:

    private List<Students> LazyStudents;

    public List<Students> StudentsProperty
    {
        get
        {
            if (LazyStudents == null)
                LazyStudents = LoadStudensList();
            return LazyStudents;
        }
    }

它们在概念上应该是同一个东西。除了多线程安全措施、调试和其他可能令人讨厌的细节外,大多数时间都没有区别。

在调试器中看到值的问题有点复杂。查看 Lazy source,它 应该 在调试器中显示 null,感谢 internal T ValueForDebugDisplay。但是,您并不是在看懒惰的价值。通过查看 Students.StudentsProperty 你正在查看你的 get 并且调试器评估 getters 而你的 getter 强制 Lazy 评估。您已经绕过了 MS 为我们创建的所有调试代码。直接公开 Lazy,这是注定的。或者,而不是调试器,将日志放入 LoadStudensList()

底线:Lazy 只是在调用 Value 之前是懒惰的。