欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C# dynamic類型使用詳解

 更新時(shí)間:2024年12月31日 09:10:23   作者:我是唐青楓  
C#中的dynamic類型允許在運(yùn)行時(shí)確定對(duì)象的類型和成員,跳過(guò)編譯時(shí)類型檢查,適用于處理未知類型的對(duì)象或與動(dòng)態(tài)語(yǔ)言互操作,dynamic支持動(dòng)態(tài)成員解析、添加和刪除動(dòng)態(tài)成員,但性能開(kāi)銷較大,類型安全性和調(diào)試?yán)щy

簡(jiǎn)介

C# 中的 dynamic 是一種特殊類型,它允許在運(yùn)行時(shí)確定對(duì)象的類型和成員,而不是在編譯時(shí)。

dynamic 的定義

  • dynamic 是一種類型,它告訴編譯器對(duì)其進(jìn)行“動(dòng)態(tài)類型解析”。
  • dynamic 類型的變量會(huì)跳過(guò)編譯時(shí)類型檢查,所有的操作會(huì)推遲到運(yùn)行時(shí)進(jìn)行。
  • 適合處理未知類型的對(duì)象,或需要與動(dòng)態(tài)語(yǔ)言(如 Python、JavaScript)互操作的場(chǎng)景。

dynamic 的使用

動(dòng)態(tài)類型賦值

dynamic obj = 10;  // 可以是整數(shù)
obj = "Hello";     // 可以變成字符串
obj = new { Name = "John", Age = 30 }; // 也可以是匿名類型

訪問(wèn)成員

動(dòng)態(tài)對(duì)象的成員在運(yùn)行時(shí)解析,因此可以訪問(wèn)任意成員:

如果訪問(wèn)了不存在的成員,運(yùn)行時(shí)會(huì)拋出 RuntimeBinderException。

dynamic obj = new { Name = "John", Age = 30 };
Console.WriteLine(obj.Name); // 輸出: John

動(dòng)態(tài)方法調(diào)用

dynamic math = new { Add = (Func<int, int, int>)((x, y) => x + y) };
Console.WriteLine(math.Add(2, 3)); // 輸出: 5

dynamic 的核心特性

與編譯時(shí)類型(靜態(tài)類型)的區(qū)別:

  • 編譯時(shí)檢查:dynamic 不會(huì)在編譯時(shí)檢查類型或成員是否存在,所有操作推遲到運(yùn)行時(shí)。
  • 靜態(tài)類型:object 和其他類型在編譯時(shí)進(jìn)行類型檢查。
object obj1 = 10;
// obj1.SomeMethod(); // 編譯錯(cuò)誤:object 沒(méi)有 SomeMethod 方法

dynamic obj2 = 10;
// obj2.SomeMethod(); // 編譯通過(guò),但運(yùn)行時(shí)拋出異常

類型推斷

動(dòng)態(tài)類型在運(yùn)行時(shí)確定,而靜態(tài)類型通過(guò)編譯器推斷:

dynamic dynamicVariable = 123; // 編譯器不檢查類型
int staticVariable = 123;      // 編譯器推斷為 int

object obj = "Hello";
// Console.WriteLine(obj.Length); // 編譯錯(cuò)誤
Console.WriteLine(((string)obj).Length); // 強(qiáng)制轉(zhuǎn)換

dynamic dyn = "Hello";
Console.WriteLine(dyn.Length); // 運(yùn)行時(shí)解析,編譯通過(guò)

使用場(chǎng)景

  • 與動(dòng)態(tài)語(yǔ)言交互:調(diào)用動(dòng)態(tài)語(yǔ)言的 API,如 COM 對(duì)象、IronPython
  • JSONXML 數(shù)據(jù)處理:在處理結(jié)構(gòu)未知的數(shù)據(jù)時(shí)動(dòng)態(tài)解析。
  • 匿名類型和動(dòng)態(tài)擴(kuò)展:快速訪問(wèn)動(dòng)態(tài)創(chuàng)建的對(duì)象。

注意事項(xiàng)

  • 性能開(kāi)銷:動(dòng)態(tài)綁定會(huì)引入性能開(kāi)銷,因?yàn)榻馕鍪窃谶\(yùn)行時(shí)完成的。
  • 類型安全:缺乏編譯時(shí)類型檢查,可能導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。
  • 調(diào)試?yán)щy:錯(cuò)誤可能難以發(fā)現(xiàn),尤其是在復(fù)雜場(chǎng)景中。

ExpandoObject 與 dynamic

ExpandoObject 是一個(gè)動(dòng)態(tài)對(duì)象,可在運(yùn)行時(shí)動(dòng)態(tài)添加或刪除成員:

常用于需要靈活擴(kuò)展的場(chǎng)景,如 JSON 數(shù)據(jù)的解析

using System.Dynamic;

dynamic expando = new ExpandoObject();
expando.Name = "John";
expando.Age = 30;

Console.WriteLine($"{expando.Name}, {expando.Age}");

ExpandoObject 內(nèi)部實(shí)現(xiàn)機(jī)制

ExpandoObject 實(shí)現(xiàn)了以下關(guān)鍵接口:

  • IDynamicMetaObjectProvider:提供動(dòng)態(tài)行為(如動(dòng)態(tài)調(diào)用、成員訪問(wèn))的核心接口。
  • IDictionary<string, object>:內(nèi)部使用一個(gè) Dictionary <string, object> 存儲(chǔ)動(dòng)態(tài)添加的成員。
using System.Dynamic;

dynamic expando = new ExpandoObject();
expando.Name = "John"; // 動(dòng)態(tài)添加成員
Console.WriteLine(expando.Name); // 動(dòng)態(tài)訪問(wèn)成員

// 等價(jià)于:
var expando = new ExpandoObject() as IDictionary<string, object>;
expando["Name"] = "John";
Console.WriteLine(expando["Name"]);

ExpandoObject 如何實(shí)現(xiàn)動(dòng)態(tài)性?

ExpandoObject 使用動(dòng)態(tài)綁定和元對(duì)象來(lái)實(shí)現(xiàn)動(dòng)態(tài)行為:

  • 動(dòng)態(tài)綁定:通過(guò) IDynamicMetaObjectProvider,在運(yùn)行時(shí)解析屬性、方法等訪問(wèn)請(qǐng)求。
  • 內(nèi)部字典:通過(guò) Dictionary<string, object> 存儲(chǔ)成員。
  • 元對(duì)象:ExpandoObject 的動(dòng)態(tài)行為由一個(gè)元對(duì)象 ExpandoMetaObject 提供支持,它負(fù)責(zé)解釋動(dòng)態(tài)操作并將其映射到內(nèi)部字典。

ExpandoObject 線程安全性

  • ExpandoObject 本質(zhì)上不是線程安全的,因?yàn)樗试S動(dòng)態(tài)修改成員。
  • 在多線程場(chǎng)景下,需要通過(guò)顯式鎖定來(lái)確保線程安全。

ExpandoObject 使用示例

  • 動(dòng)態(tài)添加/刪除成員
dynamic expando = new ExpandoObject();
expando.Name = "John";
expando.Age = 30;

// 刪除成員
var dict = (IDictionary<string, object>)expando;
dict.Remove("Age");

// 檢查成員
Console.WriteLine(dict.ContainsKey("Name")); // True
Console.WriteLine(dict.ContainsKey("Age"));  // False
  • 結(jié)合 LINQ 查詢

因?yàn)?ExpandoObject 實(shí)現(xiàn)了 IDictionary<string, object>,可以結(jié)合 LINQ 操作:

dynamic expando = new ExpandoObject();
expando.Name = "John";
expando.Age = 30;

var dict = (IDictionary<string, object>)expando;
var filtered = dict.Where(kv => kv.Key.StartsWith("N"));

foreach (var kv in filtered)
{
    Console.WriteLine($"{kv.Key}: {kv.Value}");
}

綜合考慮

1.使用 dynamic 的場(chǎng)景:

  • 與外部動(dòng)態(tài)類型(如 COM、動(dòng)態(tài)語(yǔ)言)交互。
  • 動(dòng)態(tài)調(diào)用方法或訪問(wèn)屬性,無(wú)需構(gòu)建明確的對(duì)象。
  • 臨時(shí)需要?jiǎng)討B(tài)行為,但不需要?jiǎng)討B(tài)修改成員。

2.使用 ExpandoObject 的場(chǎng)景:

  • 需要構(gòu)建動(dòng)態(tài)擴(kuò)展的對(duì)象。
  • 動(dòng)態(tài)添加和刪除屬性。
  • 構(gòu)建輕量級(jí)、靈活的業(yè)務(wù)模型。

選擇建議

特性dynamicExpandoObject
動(dòng)態(tài)成員解析支持任意動(dòng)態(tài)成員,解析時(shí)運(yùn)行時(shí)檢查只能操作明確添加到對(duì)象的動(dòng)態(tài)成員
動(dòng)態(tài)成員添加/刪除不支持支持(通過(guò)字典實(shí)現(xiàn))
類型檢查編譯時(shí)無(wú)類型檢查,運(yùn)行時(shí)解析同樣運(yùn)行時(shí)解析
適合的場(chǎng)景動(dòng)態(tài)語(yǔ)言互操作、臨時(shí)操作、反射動(dòng)態(tài)構(gòu)建對(duì)象、領(lǐng)域模型擴(kuò)展
性能比靜態(tài)類型慢,因?yàn)檫\(yùn)行時(shí)動(dòng)態(tài)綁定更高效,基于字典實(shí)現(xiàn)
實(shí)現(xiàn)復(fù)雜度動(dòng)態(tài)行為由 CLR 處理由 ExpandoObject 自行實(shí)現(xiàn)動(dòng)態(tài)行為
對(duì)字典的支持不支持內(nèi)部就是 IDictionary<string, object>
安全性運(yùn)行時(shí)錯(cuò)誤較多,調(diào)試復(fù)雜動(dòng)態(tài)但有一定約束

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#往線程里傳遞參數(shù)的方法小結(jié)

    C#往線程里傳遞參數(shù)的方法小結(jié)

    這篇文章主要介紹了C#往線程里傳參數(shù)的方法小結(jié)的相關(guān)資料,還給大家簡(jiǎn)單說(shuō)明下傳參的兩種方式,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-07-07
  • C#/VB.NET實(shí)現(xiàn)從PPT中提取圖片的示例代碼

    C#/VB.NET實(shí)現(xiàn)從PPT中提取圖片的示例代碼

    PPT是用于制作幻燈片(演示文稿)的應(yīng)用軟件,每張幻燈片中都可以包含文字、圖形、圖形、表格、聲音和影像等多種信息。本文主要介紹了如何實(shí)現(xiàn)從PPT中提取圖片的功能,需要的可以參考一下
    2023-03-03
  • C#實(shí)現(xiàn)簡(jiǎn)單的JSON序列化功能代碼實(shí)例

    C#實(shí)現(xiàn)簡(jiǎn)單的JSON序列化功能代碼實(shí)例

    這篇文章主要介紹了C#實(shí)現(xiàn)簡(jiǎn)單的JSON序列化功能,大家可以參考使用
    2013-11-11
  • C# 數(shù)據(jù)驗(yàn)證Regex示例詳解

    C# 數(shù)據(jù)驗(yàn)證Regex示例詳解

    文章介紹了C#中使用Regex進(jìn)行數(shù)據(jù)驗(yàn)證的方法,包括整數(shù)和小數(shù)的正負(fù)驗(yàn)證,以及郵箱和身份證號(hào)的格式驗(yàn)證,感興趣的朋友一起看看吧
    2025-02-02
  • c#開(kāi)發(fā)word批量轉(zhuǎn)pdf源碼分享

    c#開(kāi)發(fā)word批量轉(zhuǎn)pdf源碼分享

    已經(jīng)安裝有Office環(huán)境,借助一些簡(jiǎn)單的代碼即可實(shí)現(xiàn)批量Word轉(zhuǎn)PDF,看下面的實(shí)例源碼吧
    2013-12-12
  • Unity?UGUI的StandaloneInputModule標(biāo)準(zhǔn)輸入模塊組件使用示例

    Unity?UGUI的StandaloneInputModule標(biāo)準(zhǔn)輸入模塊組件使用示例

    這篇文章主要為大家介紹了Unity?UGUI的StandaloneInputModule標(biāo)準(zhǔn)輸入模塊組件使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • C#與PHP的md5計(jì)算結(jié)果不同的解決方法

    C#與PHP的md5計(jì)算結(jié)果不同的解決方法

    今天在用C#接入我的登錄api發(fā)現(xiàn)了一個(gè)問(wèn)題,登陸的時(shí)候無(wú)論如何都會(huì)出現(xiàn)用戶名和密碼錯(cuò)誤的問(wèn)題,后來(lái)通過(guò)查找排除找的了問(wèn)題的原因是因?yàn)镃#與PHP的md5計(jì)算結(jié)果不同導(dǎo)致的,下面就來(lái)看看如何解決這個(gè)問(wèn)題吧。
    2016-12-12
  • C#?線程切換后上下文都去了哪里(.NET高級(jí)調(diào)試分析)

    C#?線程切換后上下文都去了哪里(.NET高級(jí)調(diào)試分析)

    總會(huì)有一些朋友問(wèn)一個(gè)問(wèn)題,在 Windows 中線程做了上下文切換,請(qǐng)問(wèn)被切的線程他的寄存器上下文都去了哪里?這個(gè)問(wèn)題其實(shí)比較底層,如果對(duì)操作系統(tǒng)沒(méi)有個(gè)體系層面的理解以及做過(guò)源碼分析,其實(shí)很難說(shuō)明白,這篇我們就從.NET高級(jí)調(diào)試的角度分析,需要的朋友可以參考下
    2023-12-12
  • Visual C#類的定義及實(shí)現(xiàn)方法實(shí)例解析

    Visual C#類的定義及實(shí)現(xiàn)方法實(shí)例解析

    這篇文章主要介紹了Visual C#類的定義及實(shí)現(xiàn)方法實(shí)例解析,對(duì)于新手來(lái)說(shuō)有不錯(cuò)的借鑒學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2014-07-07
  • C#實(shí)現(xiàn)二叉查找樹(shù)

    C#實(shí)現(xiàn)二叉查找樹(shù)

    本文詳細(xì)講解了C#實(shí)現(xiàn)二叉查找樹(shù)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04

最新評(píng)論