數據類型和特殊類型-C#

来源:https://www.cnblogs.com/taotaozhuanyong/archive/2019/09/21/11563342.html
-Advertisement-
Play Games

參考地址:https://blog.csdn.net/qiaoquan3/article/details/51380992 1、集合set:純粹的數據集合 2、線性結構:一對一的,數組 3、樹形結構:一對多的,菜單/文件夾/類別/屬性控制項/表達式目錄樹 4、圖形/網狀結構:多對多,地圖應用比較多,網 ...


參考地址:https://blog.csdn.net/qiaoquan3/article/details/51380992

1、集合set:純粹的數據集合

2、線性結構:一對一的,數組

3、樹形結構:一對多的,菜單/文件夾/類別/屬性控制項/表達式目錄樹

4、圖形/網狀結構:多對多,地圖應用比較多,網站的應用比較少

 

線性結構:

Array/ArrayList/List/LinkedList/Queue/Stack/HastSet/SortedSet/Hashtable/SortedList/Dictionary/SortedDictionary

IEnumerable、ICollection、IList、IQueryable

介面是標機功能的,不同的介面岔開,就是為了介面隔離;雖然我們介面內容也可以復用。

IEnumerable任何數據集合,都實現了的,為不同的數據結構,提供了統一數據訪問方式,這個就是迭代器模式。

1、記憶體連續存儲,節約空間,可以索引訪問,讀取速度快,增刪慢

  Array:在記憶體上連續分配的,而且元素類型是一樣的。

 int[] intArray = new int[3];
 intArray[0] = 123;
 string[] stringArray = new string[] { "123", "234" };//Array

  ArrayList:不定長的,連續分配的;元素沒有類型限制,任何元素都是當成object處理,如果是值類型,會有裝箱操作;讀取快,增刪慢。

 ArrayList arrayList = new ArrayList();
 arrayList.Add("Bingle1");
 arrayList.Add("Bingle2");
 arrayList.Add(32);//add增加長度
 //arrayList[4] = 26;//索引複製,不會增加長度
 //刪除數據
 //arrayList.RemoveAt(4);
 var value = arrayList[2];
 arrayList.RemoveAt(0);
 arrayList.Remove("Bingle2");

  List<T>:也是Array,記憶體上都是連續拜訪的;不定長;泛型,保證類型安全,避免裝箱拆箱;讀取快,增刪慢。

List<int> intList = new List<int>() { 1, 2, 3, 4 };
intList.Add(123);
intList.Add(123);
//intList.Add("123");
//intList[0] = 123;
List<string> stringList = new List<string>();
//stringList[0] = "123";//異常的
foreach (var item in intList)
{

}

2、非連續拜訪的,存儲數據+地址,找書的話就只能順序查找,讀取就比較慢,增刪快

  LinkedList<T>:泛型的特點;鏈表,元素不連續分配,每個元素都有記錄前後節點;節點值可以重覆。能不能下標訪問?不能的,找元素就只能遍歷,查找不方便,增刪就比較方便。

 LinkedList<int> linkedList = new LinkedList<int>();
 //linkedList[3]
 linkedList.AddFirst(123);
 linkedList.AddLast(456);

 bool isContain = linkedList.Contains(123);
 LinkedListNode<int> node123 = linkedList.Find(123);  //元素123的位置  從頭查找
 linkedList.AddBefore(node123, 123);
 linkedList.AddBefore(node123, 123);
 linkedList.AddAfter(node123, 9);

 linkedList.Remove(456);
 linkedList.Remove(node123);
 linkedList.RemoveFirst();
 linkedList.RemoveLast();
 linkedList.Clear();

  Queue:就是鏈表,先進先出,放任務延遲執行,A不斷寫入日誌任務,B不斷獲取任務去執行

 Queue<string> numbers = new Queue<string>();
 numbers.Enqueue("one");
 numbers.Enqueue("two");
 numbers.Enqueue("three");
 numbers.Enqueue("four");
 numbers.Enqueue("four");
 numbers.Enqueue("five");

 foreach (string number in numbers)
 {
     Console.WriteLine(number);
 }

 Console.WriteLine($"Dequeuing '{numbers.Dequeue()}'");
 Console.WriteLine($"Peek at next item to dequeue: { numbers.Peek()}");
 Console.WriteLine($"Dequeuing '{numbers.Dequeue()}'");

 Queue<string> queueCopy = new Queue<string>(numbers.ToArray());
 foreach (string number in queueCopy)
 {
     Console.WriteLine(number);
 }

 Console.WriteLine($"queueCopy.Contains(\"four\") = {queueCopy.Contains("four")}");
 queueCopy.Clear();
 Console.WriteLine($"queueCopy.Count = {queueCopy.Count}");

  Stack:就是鏈表,先進後出,解析表達式目錄樹的時候,先產生的數據後使用。操作記錄為命令,撤銷的時候是倒敘的。

 Stack<string> numbers = new Stack<string>();
 numbers.Push("one");
 numbers.Push("two");
 numbers.Push("three");
 numbers.Push("four");
 numbers.Push("five");//放進去

 foreach (string number in numbers)
 {
     Console.WriteLine(number);
 }

 Console.WriteLine($"Pop '{numbers.Pop()}'");//獲取並移除
 Console.WriteLine($"Peek at next item to dequeue: { numbers.Peek()}");//獲取不移除
 Console.WriteLine($"Pop '{numbers.Pop()}'");

 Stack<string> stackCopy = new Stack<string>(numbers.ToArray());
 foreach (string number in stackCopy)
 {
     Console.WriteLine(number);
 }

 Console.WriteLine($"stackCopy.Contains(\"four\") = {stackCopy.Contains("four")}");
 stackCopy.Clear();
 Console.WriteLine($"stackCopy.Count = {stackCopy.Count}");

  隊列是沒有底的瓶子,棧是有底的瓶子

  集合:純粹的集合,容器,東西丟進去,唯一性,無序的。

  HashSet:hash分佈,元素間沒有關係,動態增加容量,去重的。統計用戶IP;IP投票;交叉並補;二次好友/間接關註/粉絲集合

 HashSet<string> hashSet = new HashSet<string>();
 hashSet.Add("123");
 hashSet.Add("689");
 hashSet.Add("456");
 hashSet.Add("12435");
 hashSet.Add("12435");
 hashSet.Add("12435");

HashSet<string> hashSet1 = new HashSet<string>();
 hashSet1.Add("123");
 hashSet1.Add("689");
 hashSet1.Add("789");
 hashSet1.Add("12435");
 hashSet1.Add("12435");
 hashSet1.Add("12435");
 hashSet1.SymmetricExceptWith(hashSet);//
 hashSet1.UnionWith(hashSet);//
 hashSet1.ExceptWith(hashSet);//
 hashSet1.IntersectWith(hashSet);//

 

  SortSet:排序的集合;去重而且排序;統計排名,每統計一個就丟進去集合

 SortedSet<string> sortedSet = new SortedSet<string>();
 //IComparer<T> comparer  自定義對象要排序,就用這個指定
 sortedSet.Add("123");
 sortedSet.Add("689");
 sortedSet.Add("456");
 sortedSet.Add("12435");
 sortedSet.Add("12435");
 sortedSet.Add("12435"); 

SortedSet<string> sortedSet1 = new SortedSet<string>();
 sortedSet1.Add("123");
 sortedSet1.Add("689");
 sortedSet1.Add("456");
 sortedSet1.Add("12435");
 sortedSet1.Add("12435");
 sortedSet1.Add("12435");
 sortedSet1.SymmetricExceptWith(sortedSet);//
 sortedSet1.UnionWith(sortedSet);//
 sortedSet1.ExceptWith(sortedSet);//
 sortedSet1.IntersectWith(sortedSet);//

  讀取和增刪都快的,有沒有?有,hash散列,字典。是key-value,一段連續空間放value(開闢的空間比用到的多,hash使用空間換性能),基於key散列計算得到地址索引,這樣讀取快,但是沒有數組快。增刪也快,刪除時也是計算位置,增加也不影響別人。代價就是,肯定會出現2個key(散列衝突),散列結果一致,可以讓第二次的+1;可能會造成效率的降低,尤其是數據量大的情況下,以前測試Dictionary在3W條左右的時候,性能愛是下降的厲害。

  Hashtable---key-value,體積可以動態增加,拿著key計算下一個地址,然後放入key-value;object-裝箱茶香,如果不同的key得到相同的地址,第二個在前面地址上+1;查找的時候,如果地址對應數據的key不對,那就+1查找。。

  浪費了空間,Hashtable是基於數組實現;查找個數據,一次定位;增刪,一次定位;增刪改查都很快,但是浪費空間,數據太多,重覆定位定位,效率就下去了。

 Hashtable table = new Hashtable();
 table.Add("123", "456");
 table[234] = 456;
 table[234] = 567;
 table[32] = 4562;
 table[1] = 456;
 table["eleven"] = 456;
 foreach (DictionaryEntry objDE in table)
 {
     Console.WriteLine(objDE.Key.ToString());
     Console.WriteLine(objDE.Value.ToString());
 }
 //線程安全
 Hashtable.Synchronized(table);//只有一個線程寫  多個線程讀

字典:泛型;key - value,增刪查改 都很快;有序的。但是欄位不是線程安全的,ConcurrentDictionary

 Dictionary<int, string> dic = new Dictionary<int, string>();
 dic.Add(1, "HaHa");
 dic.Add(5, "HoHo");
 dic.Add(3, "HeHe");
 dic.Add(2, "HiHi");
 dic.Add(4, "HuHu1");
 dic[4] = "HuHu";
 dic.Add(4, "HuHu");
 foreach (var item in dic)
 {
     Console.WriteLine($"Key:{item.Key}, Value:{item.Value}");
 }

我們來看一下List,如下圖

 

 List集合為什麼會繼承這麼多介面呢?

  1、ICollection:

    Count、IsReadOnly、Add、Clear、Contains、CopyTo、Clear

  2、IList:

    T this[int index] (索引)、IndexoOf、.....

  3、IEnumerable:

    遍歷才會去查詢比較,迭代器 yield

    GetEnumerator:Current、MoveNext、Reset

    任何數據集合,都實現了IEnumerable,為不同的數據結構提供了統一的數據訪問方式,這個就是迭代器模式。

  4、IQueryable:

    表達式目錄樹的解析,延遲到遍歷的時候才去執行,EF的延遲查詢

    IQueryProvider Provider{get;}

    

yield是語法糖,編譯時由編譯器生成Iterrator的代碼,包括movenext current  reset

  含有yield的函數說明它是一個生成器,而不是普通的函數。當程式運行到yield這一行時,該函數會返回值,並保存當前域的所有變數狀態;等到該函數下一次被調用時,會從上一次中斷的地方開始執行,一直遇到下一個yield, 程式返回值, 併在此保存當前狀態; 如此反覆,直到函數正常執行完成。

   迭代器模式是設計模式中行為模式(behavioral pattern)的一個例子,他是一種簡化對象間通訊的模式,也是一種非常容易理解和使用的模式。簡單來說,迭代器模式使得你能夠獲取到序列中的所有元素 而不用關心是其類型是array,list,linked list或者是其他什麼序列結構。這一點使得能夠非常高效的構建數據處理通道(data pipeline)。

  --即數據能夠進入處理通道,進行一系列的變換,或者過濾,然後得到結果。事實上,這正是LINQ的核心模式。

  在.NET中,迭代器模式被IEnumerator和IEnumerable及其對應的泛型介面所封裝。如果一個類實現了IEnumerable接 口,那麼就能夠被迭代;調用GetEnumerator方法將返回IEnumerator介面的實現,它就是迭代器本身。迭代器類似資料庫中的游標,他是 數據序列中的一個位置記錄。迭代器只能向前移動,同一數據序列中可以有多個迭代器同時對數據進行操作。

下麵是一個yield的一個簡單Demo:

public class YieldShow
{
    public IEnumerable<int> CreateEnumerable()
    {
        try
        {
            Console.WriteLine("{0} CreateEnumerable()方法開始", DateTime.Now);
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("{0}開始 yield {1}", DateTime.Now, i);
                yield return i;
                Console.WriteLine("{0}yield 結束", DateTime.Now);
                if (i == 4)
                {
                    yield break;//直接終結迭代  4會出現的,,
                }
            }
            Console.WriteLine("{0} Yielding最後一個值", DateTime.Now);
            yield return -1;
            Console.WriteLine("{0} CreateEnumerable()方法結束", DateTime.Now);
        }
        finally
        {
            Console.WriteLine("停止迭代!");
        }
    }
 IEnumerable<int> iterable = this.CreateEnumerable();//1 不會直接執行
 //IEnumerator iterator = iterable.GetEnumerator();
 IEnumerator<int> iterator = iterable.GetEnumerator();
 Console.WriteLine("開始迭代");
 while (true)
 {
     Console.WriteLine("調用MoveNext方法……");
     Boolean result = iterator.MoveNext();//2 正式開啟CreateEnumerable
     Console.WriteLine("MoveNext方法返回的{0}", result);
     if (!result)
     {
         break;
     }
     Console.WriteLine("獲取當前值……");
     Console.WriteLine("獲取到的當前值為{0}", iterator.Current);
 }
View Code

 

public class YieldDemo
{
    public IEnumerable<int> Power()
    {
        for (int i = 0; i < 10; i++)
        {
            yield return this.Get(i);

            //Console.WriteLine("這裡再來一次");
            //yield return this.Get(i) + 1;
        }
    }

    public IEnumerable<int> Common()
    {
        List<int> intList = new List<int>();
        for (int i = 0; i < 10; i++)
        {
            intList.Add(this.Get(i));
        }
        return intList;
    }

    private int Get(int num)
    {
        Thread.Sleep(2000);
        return num * DateTime.Now.Second;
    }
}



 YieldDemo yieldDemo = new YieldDemo();
 foreach (var item in yieldDemo.Power())
 {
     Console.WriteLine(item);//按需獲取,要一個拿一個
     if (item > 100)
         break;
 }
 Console.WriteLine("*******************************************");
 foreach (var item in yieldDemo.Common())
 {
     Console.WriteLine(item);//先全部獲取,然後一起返還
     if (item > 100)
         break;
 }
View Code

dynamic關鍵字:

  .NET Framework4.0出現的,讓程式有了弱類型的特點;

  強類型特點:

    編譯時完成安全檢查

  弱類型:

    運行時才檢查類型

 object A = new YieldDemo();
 //A.Power();
 Type type = A.GetType();
 MethodInfo method = type.GetMethod("Power");
 method.Invoke(A, null);

 dynamic dA = A;
 dA.Power();
 //1 代替反射  2 數據綁定方便 3 跟C++交互方便
 //性能比反射高
dynamic str = "abcd";//任何跟dynamic交互,都變成dynamic
Console.WriteLine(str.Length);
Console.WriteLine(str.Substring(1));

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • #set指令 #set指令用於向一個變數或者對象賦值。 格式: #set($var = value) LHS是一個變數,不要使用特殊字元例如英文句號等,不能用大括弧括起來。測試發現#set($user.name = 'zhangsan'),#set(${age} = 18)均賦值失敗。 RHS可以是 ...
  • 前言 說實話,這章本來不打算講的,因為配置多數據源的網上有很多類似的教程。但是最近因為項目要用到分庫分表,所以讓我研究一下看怎麼實現。我想著上一篇博客講了多環境的配置,不同的環境調用不同的資料庫,那接下來就將一個環境用到多個庫也就講了。所以才有了這篇文章。 我們先來看一下今天項目的項目結構,在上篇博 ...
  • 最近做了一些.NET Core的程式,有在Windows下運行的 有在CentOS 下運行的,Windows下運行的還好,對Windows下還算比較熟悉了,但CentOS 下 每次都是找筆記支持命令 於是今天晚上就乾脆把以.NET Core程式已服務形式啟動的代碼封裝了下,代碼 主要是便於安裝。 我 ...
  • Excel文件讀、寫可以使用Office自帶的庫(Microsoft.Office.Interop.Excel),前提是本機須安裝office才能運行,且不同的office版本之間可能會有相容問題。還可以使用NPOI,在不安裝office的時候也是可以讀寫的,速度很快。當然,還有支持Excel200 ...
  • 第一次接觸到Cache的時候,是在WebForm中,第一次接觸,我就再也沒能忘記,cache(擦車,的拼音) 客戶端瀏覽器緩存https://blog.csdn.net/y874961524/article/details/61419716 CDN緩存原理https://www.cnblogs.co ...
  • 因為有時候需要定製化的控制項,需要多個控制項的組合及複雜功能的集成,這樣可以考慮自定義用戶控制項。下麵分享一個簡單的數值增減功能的自定義控制項作為說明。 效果圖如下: 1、創建自定義用戶控制項(添加->新建項->用戶控制項) 2、編寫XAML UI比較簡單,我就不解釋了... 2、編寫後臺代碼 邏輯也比較簡單, ...
  • WPF依賴項屬性可以實現屬性的綁定,成功綁定之後只要修改後臺綁定的屬性,即可UI同步自動更新綁定的值,無需手動刷新界面;同樣,前臺的值變化後,通過獲取綁定的屬性值也可獲取UI變化後的值,實現雙向變化的效果。屬性綁定使得UI更新非常的方便,下麵分享一個小慄子說明使用的方式。 1、先做了一個有一個Tex ...
  • JIT--第一次--標記已--存根--調用--查找存根--執行機器碼 C#和CIL的關係: C#和N#都是CIL實現,但是彼此不能互通: C#和N#公開不分滿足規範,我們才能互通 CLS就是描述多語言互通的規範 記憶體分配:線程棧 堆Heap: 一個程式運行時,該進程存放引用類型變數的一塊記憶體,全局唯 ...
一周排行
    -Advertisement-
    Play Games
  • 基於.NET Framework 4.8 開發的深度學習模型部署測試平臺,提供了YOLO框架的主流系列模型,包括YOLOv8~v9,以及其系列下的Det、Seg、Pose、Obb、Cls等應用場景,同時支持圖像與視頻檢測。模型部署引擎使用的是OpenVINO™、TensorRT、ONNX runti... ...
  • 十年沉澱,重啟開發之路 十年前,我沉浸在開發的海洋中,每日與代碼為伍,與演算法共舞。那時的我,滿懷激情,對技術的追求近乎狂熱。然而,隨著歲月的流逝,生活的忙碌逐漸占據了我的大部分時間,讓我無暇顧及技術的沉澱與積累。 十年間,我經歷了職業生涯的起伏和變遷。從初出茅廬的菜鳥到逐漸嶄露頭角的開發者,我見證了 ...
  • C# 是一種簡單、現代、面向對象和類型安全的編程語言。.NET 是由 Microsoft 創建的開發平臺,平臺包含了語言規範、工具、運行,支持開發各種應用,如Web、移動、桌面等。.NET框架有多個實現,如.NET Framework、.NET Core(及後續的.NET 5+版本),以及社區版本M... ...
  • 前言 本文介紹瞭如何使用三菱提供的MX Component插件實現對三菱PLC軟元件數據的讀寫,記錄了使用電腦模擬,模擬PLC,直至完成測試的詳細流程,並重點介紹了在這個過程中的易錯點,供參考。 用到的軟體: 1. PLC開發編程環境GX Works2,GX Works2下載鏈接 https:// ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • 1、jQuery介紹 jQuery是什麼 jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之後又一個優秀的JavaScript代碼庫(或JavaScript框架)。jQuery設計的宗旨是“write Less,Do More”,即倡導寫更少的代碼,做更多的事情。它封裝 ...
  • 前言 之前的文章把js引擎(aardio封裝庫) 微軟開源的js引擎(ChakraCore))寫好了,這篇文章整點js代碼來測一下bug。測試網站:https://fanyi.youdao.com/index.html#/ 逆向思路 逆向思路可以看有道翻譯js逆向(MD5加密,AES加密)附完整源碼 ...
  • 引言 現代的操作系統(Windows,Linux,Mac OS)等都可以同時打開多個軟體(任務),這些軟體在我們的感知上是同時運行的,例如我們可以一邊瀏覽網頁,一邊聽音樂。而CPU執行代碼同一時間只能執行一條,但即使我們的電腦是單核CPU也可以同時運行多個任務,如下圖所示,這是因為我們的 CPU 的 ...
  • 掌握使用Python進行文本英文統計的基本方法,並瞭解如何進一步優化和擴展這些方法,以應對更複雜的文本分析任務。 ...
  • 背景 Redis多數據源常見的場景: 分區數據處理:當數據量增長時,單個Redis實例可能無法處理所有的數據。通過使用多個Redis數據源,可以將數據分區存儲在不同的實例中,使得數據處理更加高效。 多租戶應用程式:對於多租戶應用程式,每個租戶可以擁有自己的Redis數據源,以確保數據隔離和安全性。 ...