數往知來C#之 String 集合 深拷與淺拷 序列化<五>

C# 基礎經常使用string方法篇

複習、
一、引用類型與值類型
    --》文件的複製與快捷方式的複製
二、垃圾回收
程序員

三、靜態與非靜態
  --》如何定義靜態成員與靜態類
  --》如何調用靜態成員
算法

四、異常數組

    -》託管與非託管
       -》.net frameworl 
主要分爲三個東西:CLR、CTS、類庫
     -》由CLR管理的代碼就是託管的,不然就是費託管的(如File.Create)
     ->異常是一個類,須要拋出一個異常就要new
  -》thorw關鍵字,拋出
2、經常使用類庫--String
大寫的String與小寫的string有什麼不一樣?
  -》能夠說兩個都同樣
  -》String是一個類
  -》構造方法    new string(char [] shs)
2)兩個經常使用的屬性(Length/Empty(常量))
  -》length   這一點與數組的用法相似
  -》str[0]這個中括號就不叫下標,叫索引
經常使用的方法(索引的使用、ToCharArrray)
不可變性
既然是不可變的,那麼多個字符串,結果相同的時候,就沒有必要每次生成一個對象(節省資源)
3)字符串拘留池(暫存池)
因爲有字符串拘留池的存在,若是代碼中有大量的字符串的值相同,那麼他們都指向同一個對象,
整個代碼中只建立一個對象。
字符串的內部實現與C語言的字符串的實現同樣,能夠參考 IL Assembly這本書
ide

4)字符串的處理經常使用的
   -》比較
       1)Equals方法
      -》靜態的Equals方法
   -》非靜態的(string的/object的)
   Equels方法法有三個重載,StringComparison是個枚舉 OrdinalIgnoreCase表示不區分大小寫比較。
      // Equals方法
            // -> 靜態的比較方法(靜態方法由類名點出來的)
工具

string str1="abcd";
   string str2="ABCD";
            if (string.Equals(str1, str2, StringComparison.OrdinalIgnoreCase))
            {
                Console.WriteLine("相等");
            }
            else
            {
                Console.WriteLine("不等");
            }
            // -> 非靜態(string的,object的)(實例方法是有對象點出來的)
            if (str1.Equals(str2, StringComparison.OrdinalIgnoreCase))
            {
                Console.WriteLine("相等");
            }
            else
            {
                Console.WriteLine("不等");
            }

   

string.Compare方法是靜態方法,比較兩個字符串大小,比較的的是沒一位字符的unicode碼,
比較規則:分別從兩個字符串的第一位兩兩相比,若是第一位相等就再比較第二位,知道比出大的爲止。
注意:如「22」和「123」相比,此時比較第一個‘2’比‘1’大,那麼就後面的不會再比較了,此時「22」比「123」大
學習

string str1="12";
   string str2="23";
     if (string.Compare(str1, str2) > 0)
            {
                Console.WriteLine("大於");
            }
            else
            {
                Console.WriteLine("小於");
            }

   

   -》修整
    Trim()方法,修整字符傳收尾的空格,,並將新的字符串返回
Trim(praram char [] chs),去除字符數組中出現的字符
TrimEnd() 去掉右邊的
TrimStart() 去掉左邊的
   -》檢索
增長:
移除
查找
  contains()
  indexof()
  lastindexof()
ui

   -》分割與合併this

   -》格式化
3、StringBuilder
   ->Appand()     追加
   -》AppandLine   追加換行 至關於 Appand(「123\n」)
   ->AppandFramart  格式化
StringBuilder輸出的時候記得要ToString()一下
spa

C#  集合篇

1)string.format  格式化字符串(就是挖坑填坑)
能夠參考console.writeline(「{0}{1}」,str1,str2);不一樣的是conbsole.writeline()是輸出,Format是把它做爲一個字符串返回。
   -》@符號的兩個好處:1)能夠取消轉義
                   2)寫字符串的時候能夠換行
2、集合
爲何要有集合?
數組不是動態的,他的長度動態的變更,爲了擬補這些就有了集合
能夠認爲,集合就是一個動態的數組,而且提供了一些處理的方法
.net

1)增、
ArrayList裏面能夠存聽任何類型的數據,裏面存放的數據類型是object的 (arraylist要引入命名空間  shift+alt+F10)
   arrayList.Add(要添加的數據);  (這是個實例方法)
   arrayList.AddRange(數組);     這裏要注意Add方法也能夠放一個數組進去,可是不一樣的是Add方法是把整個數組當成一個集合的元素存到集合裏去,
而AddRange方法是把數組的每一個元素排列放到集合裏去。
2)刪、
Remove()  把指定的元素刪除,若是集合裏沒有這個元素就會忽略掉,不會報異常
RemoveAt()  把集合裏指定下標的元素刪除,若是這個下標超出集合的長度就會報異常
3)改、
和數組同樣經過下標改。直接賦值
4)查
contains(要查找的元素)
若是集合裏有這個元素會返回一個true,不然返回false

5)插入
arrayList.Insert(要插入位置的索引,要插入的數據);

arraylist最大缺點就是Arrayliat是object類型,處理數據須要考慮類型兼容
須要把集合裏的數據拿出來的時候須要強制轉換,因爲是object類型存什麼類型的數據均可以,當集合裏存的數據多的時候
咱們強制轉換就會就會比較麻煩,爲了解決這個問題,List<>泛型集合就出現了。

2)Hashtable<鍵,值>   
   -》Hashtable的出現就是爲了讓咱們便於查找集合裏的數據的,
   -》hashtable裏面存的是一個 鍵 和 值。他們都是object類型的,能夠存聽任何類型的。
   -》hashtable的鍵就至關於一個標記,要查找的時候能夠經過 hashtable.Contains(要查找的鍵);方法就能夠快速的找到這個鍵對應着的值(它是經過一個哈希散列算法來實現的)
I、增
      hashtable.Add(鍵,值);    //hashtable只有一個增長的方法,裏面能夠聽任何類型的數據。
II、刪
Remove(鍵);
    -》咱們知道ArrayList是經過下標來刪除的,那麼 咱們的hashtable也是相同的原理,hashtable的鍵就至關於arraylist的下標,
若是把鍵改爲0、一、二、三、四、5........那麼就至關於一個ArrayList,那麼能夠獲得結論,hashtable[鍵] 經過中括號 鍵來刪除。
3、泛型集合
List<T>   這個尖括號裏寫什麼類型這個集合就存什麼類型的數據
  -》list就至關於一個規定好存放類型的ArrayList,
  ->當咱們規定好類型後就能夠解決類型兼容的問題了,從幾何裏取數據時就方便多了。
  List的增、刪、改、查方法跟ArrayList同樣。
Dictionary<鍵,值> 
    ->Dictionary對應的就是hashtable,咱們能夠規定好鍵和值的類型,使用起來更加的方便
    -》遍歷的三種方法

foreach (string item in dic.Keys)   //經過鍵來遍歷
            {
                Console.WriteLine(item);
                Console.WriteLine(dic[item]);
            }

            foreach (Person item in dic.Values)  //經過值來遍歷
            {
                Console.WriteLine(item);
            }

            foreach (KeyValuePair<string,Person> item in dic)  //咱們有時候遍歷的時候要同時用到集合的鍵和值,就能夠經過這個方法
            {                                                   //KeyValuePair也是一個集合
                Console.WriteLine(item.Key + " "+item.Value);
            }


遍歷集合用foreach,  ArrayList和hashtable使用要引入命名空間,而List和Dictionary不用,能夠看出微軟提倡咱們用 List和Dictionary

2、foreach  (能夠遍歷任何實現了IEnumerble接口的對象)
  foreach(臨時數據類型 臨時變量 in 要遍歷的集合)
  {
     //將臨時變量做爲遍歷的數據使用
  }
要知道臨時數據類型是什麼類型的能夠先寫個var 而後在下面設個斷點,再把光標放到var上去,就能夠獲得當前遍歷的集合是什麼類型了
儘可能不要用var

4、裝箱與拆箱
值類型轉換爲引用類型就是裝箱
應用類型轉換爲值類型就是拆箱

對值類型裝箱保持不變性,對引用類型不保持保持相關性()

Dotnet學習_遞歸篇

3、遞歸

遞歸就是調用本身

--》怎麼調用?(遞推關係)

--》何時跳出

等差數列

           2   4   6   8   10  ...

求第n項

               2n

           Func(n) = Func(n-1) + 2

           Func(n) = (Func(n-1-1)+2)+2

。。。

           Func(n) = (Func(1)。。。)。。。+2

寫遞歸

      --》首先要找到遞推關係

      --》臨界條件

wps71DD.tmp

wps720D.tmp

 

小練習_神探福爾摩斯小說

private void Form1_Load(object sender, EventArgs e)
        {
            //先添加一個根節點
            TreeNode tn = tvwDir.Nodes.Add("神探福爾摩斯-柯南.道爾");
            //得到文件的路徑
            string path= Path.GetFullPath ("txt");
            RecAdd(tn, path);
        }
        private void RecAdd(TreeNode tn, string path)
        {
            //得到這個路徑下的全部子目錄
            string [] dirs = Directory.GetDirectories(path);
            //得到這個路徑下的全部子文件
            string[] files = Directory.GetFiles(path);
            //循環把全部的子目錄添加到父節點下
            foreach (string item in dirs)
            {
                //從絕對路徑裏提取文件名
                string file= Path.GetFileNameWithoutExtension(item);
                TreeNode tn1= tn.Nodes.Add(file);//目錄名添加到父節點下
                //遞歸調用,由於不知道子目錄下還有多少個子目錄,因此遞歸調用
                RecAdd(tn1, item);
            }
            //循環添加全部的子文件到父節點下
            foreach (string item in files)
            {
                //一樣的須要對絕對路徑作一下處理,提取文件名
                string file = Path.GetFileNameWithoutExtension(item);
                TreeNode tn2= tn.Nodes.Add(file);//文件名添加到父節點下
                tn2.Tag = item;
                //tag屬性石用來存儲程序員須要使用的任何數據
                //把絕對路徑保存到剛添加的節點的tag屬性下,用於後面讀取文件裏的內容
            }
        }
        private void tvwDir_AfterSelect(object sender, TreeViewEventArgs e)
        {
            TreeNode tn= e.Node ;//先獲取選中的節點
            if (tn.Tag !=null)//判斷tag屬性是否是空
            {
                txtContans.Text = File.ReadAllText(tn.Tag .ToString (),Encoding .Default );
            }
        }

C#  深拷和淺拷篇

2、深拷與淺拷
拷就是拷貝、複製的意思
      --》深拷和淺拷是指堆空間裏的對象和引用類型的拷貝,而值類型不存在深拷和淺拷,由於值類型只是把值給複製了一份。
淺拷
   --》淺拷,只要有一個引用類型沒有被複制就是淺考,(複製就是產生了一個徹底沒有關係的對象,而這個對象裏德值是被複制過來的)
     

class Mark
    {
        string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
    }
    class MyClass
    {
        string _name;
        Mark mark;
        public Mark Marks
        {
            get { return mark; }
            set { mark = value; }
        }
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        public MyClass Coby()
        {
            MyClass temp=new MyClass ();
            temp.Name = this.Name;
            temp.mark = new Mark();
            temp.mark.Name = this.mark.Name;
            return temp;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            MyClass m1 = new MyClass();
            m1.Name = "張三";
            m1.Marks = new Mark();
            m1.Marks.Name = "哈哈哈";
            MyClass m = m1;   //這裏只是把m1的引用複製了一份賦給了m   並無複製m1裏的對象也沒有複製引用類型因此既不是深考也不是淺考
            MyClass m2 = new MyClass();  //淺考
            m2.Name = m1.Name;
            m2.Marks = m1.Marks;//這裏是把m1Marks裏的對象複製了,m1.marks存的引用又複製了一份賦給m2.marks此時他們都是指向了堆空間裏的另外一個對象mark,引用類型沒有被徹底複製在mark這裏斷開了,因此是淺考
            MyClass m3 = new MyClass();
            m3.Name = m1.Name;
            m3.Marks = new Mark();
            m3.Marks.Name = m1.Marks.Name;//這裏m3是從新New一個對象,而後把m1.marks.name的值複製給m3.marks.name,他們是兩個徹底不同的對象,此時m1裏的引用類型被m3徹底的複製了一份,因此叫深考,
                                                                   //只要 全部的引用類型都被複制了沒有一個被斷開就是深考
        }

wps722D.tmp

C#  序列化篇

1、序列化
爲何要序列化?    --》爲了把內存裏的數據寫到硬盤裏。
序列化首先 第一步:給類加一個標籤,標記爲能夠被序列化,要序列化的對象類與父類均需標記

[Serializable]   //標記 (特性的意思)
Class myClass
{
}
     static void Main(string[] args)
        {
            #region 傳統方法
            //Student stu = new Student();
            //stu.Name = "張三";
            //stu.Sex='男';
            //stu.Age = 20;
            ////將student對象存到
            //StringBuilder sb = new StringBuilder();
            //sb.AppendLine(stu.Name );
            //sb.AppendLine(stu.Age.ToString () );
            //sb.AppendLine(stu.Sex .ToString ());
            //File.WriteAllText("E:\\sb.txt", sb.ToString());
            //string []input= File.ReadAllLines("E:\\sb.txt");
            //Student s=new Student ();
            //s.Name = input[0];
            //s.Age =Convert .ToInt32 ( input[1]);
            //s.Sex = Convert.ToChar(input[2]);
            #endregion
            List<Student> list = new List<Student>();
            list.Add(new Student ("張三1",20,''));
            list.Add(new Student("張三2", 20, ''));
            list.Add(new Student("張三3", 20, ''));
            list.Add(new Student("張三4", 20, ''));
            list.Add(new Student("張三5", 20, ''));
            list.Add(new Student("張三6", 20, ''));
            list.Add(new Student("張三7", 20, ''));
            list.Add(new Student("張三8", 20, ''));
            list.Add(new Student("張三9", 20, ''));
            #region 榮譽代碼
            //using (FileStream file = new FileStream("E:\\1.dat", FileMode.Create, FileAccess.Write))
            //{
            //    BinaryFormatter bin = new BinaryFormatter();
            //    bin.Serialize(file, list);
            //}
            //Console.WriteLine("序列化完成");
            //using (FileStream wfile = new FileStream("E:\\1.dat", FileMode.Open, FileAccess.Read))
            //{
            //    BinaryFormatter bin=new BinaryFormatter ();
            //    Student s = (Student)bin.Deserialize(wfile);
            //}
            #endregion
            //序列化
            //首先須要一個寫得流
            using (FileStream filewrite = new FileStream("E:\\1.dat", FileMode.Create, FileAccess.Write))
            {
                //再須要一個工具
                BinaryFormatter bin = new BinaryFormatter();
                bin.Serialize(filewrite, list);  //第一個是流,第二個是對象
            }
            //反序列化
            //首先也須要一個讀的流
            using (FileStream fileread = new FileStream("E:\\1.dat", FileMode.Open, FileAccess.Read))
            {
                //再須要一個工具
                BinaryFormatter fbin = new BinaryFormatter();
                List <Student > s = (List <Student >)fbin.Deserialize(fileread);
            }
            Console.WriteLine("完成");
        }


序列化的一個應用---保存窗體上一次關閉時的位置
--》首先寫一個方法,保存窗體的位置(窗體的左上角的座標)和窗體的長和寬,在關閉窗體的時候調用這個方法。(寫在Dispose方法裏 關閉窗體時都會調用這個方法)
  

protected override void Dispose(bool disposing)
        {
            //調用保存窗體關閉時的位置大小
            Save();
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
--》而後要一個類,這個類裏面有兩個字段 來存儲窗體的location和size屬性,把這兒兩個屬性分別賦值給這個類的兩個字段
    class MyPoint
    {
        Point mPoint;
        Size mySize;
        public Point  MPoint
        {
            get;
            set;
        }
        public Size  MySize
        {
            get;
            set;
        }
    }


--》而後序列化把數據寫到硬盤裏保存,當窗體關閉的時候調用這個方法就保存了窗體關閉時的位置和大小。
--》再寫一個方法反序列化,把存到硬盤裏德數據再拿出來,寫窗體的 Lode事件(窗體啓動前都會執行lode事件,lode事件通常都用來初始化),
把定義類的兩個字段裏存的數據再賦給窗體。
   

private void Save()
        {//須要一個流
            using (FileStream filewrite = new FileStream("location.dat", FileMode.Create, FileAccess.Write))
            {
                //new一個MyPoint類用來存儲窗體的位置大小
                MyPoint mypoint = new MyPoint();
                mypoint.MPoint = this.Location;//把窗體的位置賦給字段(窗體的左上角的point)
                mypoint.MySize = this.Size;//把窗體的大小賦給字段
                //須要一個序列化的工具
                BinaryFormatter bin = new BinaryFormatter();
                //開始序列化
                bin.Serialize(filewrite, mypoint);
            }
        }
        private void ReadLocatoin()
        {
            if (File.Exists("location.dat"))//判斷一下窗體的位置大小被改變了沒有,若是改變了會產生一個"location.dat"文件
            {
                //須要一個流
                using (FileStream fileread = new FileStream("location.dat", FileMode.Open, FileAccess.Read))
                {
                    //須要一個反序列化的工具
                    BinaryFormatter bin = new BinaryFormatter();
                    //開始反序列化
                    MyPoint p = (MyPoint)bin.Deserialize(fileread);
                    //把窗體的啓動起始位置設置爲自定義
                    this.StartPosition = FormStartPosition.Manual;
                    this.Location = p.MPoint;
                    this.Size = p.MySize;
                }
            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            ReadLocatoin();
        }

//最近工做事情多,本系列下章應該會延時。

相關文章
相關標籤/搜索