【问题标题】:Why data in Lazy Loading C# is loaded before I need it?为什么延迟加载 C# 中的数据会在我需要之前加载?
【发布时间】:2021-06-23 08:40:34
【问题描述】:

在我阅读的一个网站上:

女士加载是延迟加载对象直到我们需要此数据的概念。换句话说,我们按需加载对象,而不是提前加载不必要的数据。

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

Student

 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!");
        }
    }

我想我使用延迟加载,当我创建学生类 StudentProperty 的新对象(从延迟列表返回元素)仍然为空时。当我使用使用 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 循环之前添加断点,我看到 StudentProperty 有元素:

是我错误地实现了延迟加载还是我理解错了什么?

【问题讨论】:

  • 你能澄清一下这个说法吗?:“我想我使用延迟加载,当我创建学生类 StudentProperty 的新对象(从延迟列表返回元素)仍然为空”
  • 您通过推迟实例化 Lazy&lt;T&gt; 类来滥用它。它已经处理了惰性方面,但您也可以通过检查 null 并在 StudentsProperty 中实例化它来自己处理。您应该在字段的声明点实例化Lazy&lt;T&gt;。至于为什么你可以看到 StudentsProperty 属性 - 调试器正在访问它,所以它当然会被实例化,因为调试器导致了这个!
  • 你可以通过一些例子来理解这个概念,而不是仅仅从理论上理解它codeproject.com/Articles/652556/Can-you-explain-Lazy-Loading
  • 对于初学者来说,拥有Lazy 意味着您不再需要任何类型的null 检查——只需执行readonly Lazy&lt;..&gt; = new Lazy(...)。懒惰地创建Lazy 是多余的。其次——在断点处,如果你向调试器询问StudentsProperty——你是在询问数据,所以它当然会出现!只在LoadStudensList 中设置断点而不检查表达式,跳过Main,看看它何时被调用。
  • Lazy&lt;T&gt; 基本上只是 if (x == null) x = new List&lt;T&gt;() 的快捷方式。正如其他人已经指出的那样,您可以删除您的空检查。

标签: c# lazy-loading lazy-evaluation


【解决方案1】:

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

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

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

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

    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,它应该在调试器中显示空值,这要感谢internal T ValueForDebugDisplay。但是,您不是在看惰性的价值。通过查看Students.StudentsProperty,您正在查看您的get,并且 debbuger 会评估 getter,而您的 getter 会强制 Lazy 进行评估。您已经绕过了 MS 为我们创建的所有调试代码。直接暴露Lazy,它的意思是。或者,代替调试器,在LoadStudensList() 中输入日志

底线:Lazy 仅在 Value 被调用之前是惰性的。

【讨论】:

    猜你喜欢
    • 2013-11-23
    • 2018-03-08
    • 1970-01-01
    • 1970-01-01
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-07
    相关资源
    最近更新 更多