亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

為什么我沒有收到空引用異常?

為什么我沒有收到空引用異常?

C#
Cats萌萌 2022-10-15 15:11:23
我正在使用 LINQ to Entities 從數據庫中獲取一些數據。以下是我的查詢。var location = from l in dbContext.Locationsjoin e in dbContext.Equipment on l.ID equals e.LocationID into rs1from e in rs1.DefaultIfEmpty()where ids.Contains(l.ID)select new{    EquipmentClass = e,    LocationID = l.ID,    LocationName = l.Name,    EquipmentName = e == null ? null : e.Name,    Description = e == null ? null : e.Description,    InServiceStatus = e == null ? false : e.InServiceStatus,    EquipmentType = e.EquipmentType.Name};foreach (var item in location){    // some logic}在上面的代碼中,ids是我傳入以過濾結果的整數列表。當我得到結果時,我看到其中一個返回記錄有一個 null EquipmentClass。我執行了一些空值檢查,但意識到我忘記對其中一個屬性進行空值檢查。現在我希望得到一個空引用異常,EquipmentType = e.EquipmentType.Name但我沒有。令我驚訝的是,它工作得很好,并且設置為 null。MyEquipmentClass的屬性類型為EquipmentType,這是另一個類。EquipmentType有一個Name屬性,它是一個字符串。為什么這不會引發空引用異常?就像測試一樣,我從中刪除了空檢查,InServiceStatus = e == null ? false : e.InServiceStatus并在使用查詢運行 foreach 循環時失敗并出現無效操作異常。這是否意味著我只需要對不可為空的值進行空檢查?
查看完整描述

3 回答

?
MYYA

TA貢獻1868條經驗 獲得超4個贊

如果您針對 編寫 LINQ 查詢IQueryable,會發生什么情況是您在后臺調用的方法(例如Select、Where等)除了記錄您如何調用它們之外沒有做任何其他事情,即它們記錄謂詞表達式并繼承一個 LINQ 提供程序。一旦您開始迭代查詢,就會要求提供者執行查詢模型。所以基本上,提供者使用表達式模型為您提供預期類型的結果。

提供者絕不需要實際編譯甚至執行您作為表達式交付的代碼(模型)。事實上,LINQ to SQL 或 LINQ to Entities 的全部意義在于提供程序不這樣做,而是將代碼表達式轉換為 SQL。

因此,您的查詢實際上被呈現為 SQL 查詢,并且該查詢的結果被翻譯回來。因此,您在查詢中看到的變量e不一定是真正創建的,而只是用于 LINQ 提供程序來編譯 SQL 查詢。但是,大多數數據庫服務器都有空傳播。

對 LINQ to Objects 運行相同的查詢,您將得到缺少的 NullReferenceException。


查看完整回答
反對 回復 2022-10-15
?
慕尼黑5688855

TA貢獻1848條經驗 獲得超2個贊

您的更新幫助我了解了您真正關心的問題。關于 LINQ 查詢,您需要了解的概念是 LINQ 中的延遲執行

請通過以下鏈接了解更多詳情:

LINQ 中的延遲執行有什么好處?

Linq - 找出延遲執行的最快方法是什么?

現在你的情況會怎樣?您已將查詢存儲在location變量中。該特定步驟只是初始化部分。它并沒有真正通過您的 ORM 層對您的數據庫執行查詢。這就是您可以測試的方式。

location在使用 LINQ 查詢初始化變量的代碼行上放置一個斷點。當調試器在 Visual Studio 中停止時,請轉到 SQL Server Management Studio (SSMS) 并啟動 SQL Server Profiler 會話。

現在在 Visual Studio 中按下F10以跳過代碼語句。此時,您將在分析器會話中看到絕對沒有查詢執行,如下所示:

http://img1.sycdn.imooc.com//634a5d4300017fae12140406.jpg

這都是因為 LINQ 查詢直到此時才被執行。


現在您可以訪問以下代碼行:


foreach (var item in location)

{

    var p = item.EquipmentClass.EquipmentType.Name;

}

在您進入 foreach 循環的那一刻,LINQ 查詢被觸發,您將在 SQL Server 探查器中看到相應的登錄跟蹤會話。因此,除非枚舉 LINQ 查詢,否則它不會被觸發。這稱為延遲執行,即運行時延遲執行直到枚舉。如果您從未location在代碼中枚舉變量,那么查詢執行將永遠不會發生。


因此,要回答您的查詢,只有在查詢被觸發時才會出現異常。不是在那之前!


更新 1:您是說 -我沒有得到空引用異常。是的!在您到達缺少相應 RHS 加入記錄的記錄之前,您不會得到空引用異常。請查看以下代碼以更好地理解:


class Program

{

    static void Main(string[] args)

    {

        var mylist1 = new List<MyClass1>();

        mylist1.Add(new MyClass1 { id = 1, Name1 = "1" });

        mylist1.Add(new MyClass1 { id = 2, Name1 = "2" });


        var mylist2 = new List<MyClass2>();

        mylist2.Add(new MyClass2 { id = 1, Name2 = "1" });


        var location = from l in mylist1

                       join e in mylist2 on l.id equals e.id into rs1

                       from e in rs1.DefaultIfEmpty()

                       //where ids.Contains(l.ID)

                       select new

                       {

                           EquipmentClass = e,

                           InServiceStatus = e == null ? 1 : e.id,

                           EquipmentType = e.id

                       };


        foreach (var item in location)

        {


        }

    }

}


class MyClass1

{

    public int id { get; set; }

    public string Name1 { get; set; }

}


class MyClass2

{

    public int id { get; set; }


    public string Name2 { get; set; }

}

所以,現在當我開始迭代location變量時,它不會在第一次迭代中中斷。它在第二次迭代中中斷。當它無法獲得與2 中存在的MyClass1對象對應的記錄/對象時,它會中斷。2沒有任何對象。希望這會有所幫助!idmylist1mylist2id


查看完整回答
反對 回復 2022-10-15
?
慕仙森

TA貢獻1827條經驗 獲得超8個贊

你的e.EquipmentType.Nameisnull并且它被分配給它并且分配給一個類型EquipmentType是非常好的,你正在使用它,如果它不匹配任何條件,它將使用它們的默認值初始化元素,在這種情況下,你被設置為哪個很好我猜。使用它會拋出異常。nullnullableDefaultIfEmpty()e.ElementType.NamenullToList()

我希望我說得有道理,你們可能已經討論過這個問題。


查看完整回答
反對 回復 2022-10-15
  • 3 回答
  • 0 關注
  • 142 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號