最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#不可變類型深入解析

 更新時間:2014年08月13日 11:07:06   投稿:shichen2014  
這篇文章主要介紹了C#不可變類型,對于C#程序員深入理解string數(shù)據(jù)類型有很大的幫助,需要的朋友可以參考下

學過C#的人都知道string類型,但是string作為一種特殊的引用類型還有一個重要的特征就是恒定性,或者叫不可變性,即Immutable。作為不可變類型,最主要的特性表現(xiàn)是:一旦創(chuàng)建,只要修改,就會在托管堆上創(chuàng)建一個新的對象實例,而且和上一個對象實例是相鄰的,在托管堆上分配到一塊連續(xù)的內(nèi)存空間。

那么為什么需要不可變類型呢?

在多線程情況下,一個線程,由于種種原因(比如異常)只修改了一個變量所代表類型的部分成員的值,這時候,另一個進程進來,也訪問這個變量,第二個進程訪問到的變量成員,一部分成員還是原來的值,另一部分成員的值是第一個線程修改的值,這樣就出現(xiàn)了"數(shù)據(jù)不一致"。而不可變類型就是為了解決在多線程條件下的"數(shù)據(jù)不一致"的問題。

當然,字符串的不可變性或恒定性,不僅解決了"數(shù)據(jù)不一致"的問題,還為字符串的"駐留"提供了前提,這樣才可以把不同的字符串以及托管堆上的內(nèi)存地址以鍵值對的形式放到全局哈希表中。

一、親眼目睹"數(shù)據(jù)不一致":

對Student的Score屬性,在賦值的時候加上檢測,檢測是否是2位數(shù)整數(shù)。

  public struct Student
  {
    private string name;
    private string score;
 
    public string Name
    {
      get { return name; }
      set { name = value; }
    }
 
    public string Score
    {
      get { return score; }
      set
      {
        CheckScore(value);
        score = value;
      }
    }
 
    //檢測分數(shù)是否是2位數(shù)整數(shù)
    private void CheckScore(string value)
    {
      string pattern = @"\d{2}";
      if (!Regex.IsMatch(value, pattern))
      {
        throw new Exception("不是有效分數(shù)!");
      }
    }
 
    public override string ToString()
    {
      return String.Format("姓名:{0},分數(shù):{1}", name, score);
    }
  }
 

在主程序中故意制造出一個異常,目的是只對一個變量所代表類型的某些成員賦值。

    static void Main(string[] args)
    {
      Student student = new Student();
      student.Name = "張三";
      student.Score = "80";
      Console.WriteLine(student.ToString());
 
      try
      {
        student.Name = "李四";
        student.Score = "8";
      }
      catch (Exception)
      {
        
        throw;
      }
      Console.WriteLine(student.ToString());
      Console.ReadKey();
    }
 

打斷點,運行,發(fā)現(xiàn)Student類型的student變量,在第二次賦值的時候,把student的Name屬性值改了過來,而student的Score屬性,由于發(fā)生了異常,沒有修改過來。這就是"數(shù)據(jù)不一致"。

如下圖所示:

二、動手設計不可變類型

1.不可變類型的2個特性:

①對象的原子性:要么不改,要改就把所有成員都改,從而創(chuàng)建新的對象。
②對象的常量性:對象一旦創(chuàng)建,就不能改變狀態(tài),即不能改變對象的屬性,只能創(chuàng)建新的對象。

2.遵循以上不可變類型的2個特征

①在構造函數(shù)中對所有字段賦值。
②將屬性中的set訪問器刪除。

  class Program
  {
    static void Main(string[] args)
    {
      Student student = new Student("張三", "90");
      student = new Student("李四","80");
      Console.WriteLine(student.ToString());
      Console.ReadKey();
    }
  }
 
  public struct Student
  {
    private readonly string name;
    private readonly string score;
 
    public Student(string name, string score)
    {
      this.name = name;
      this.score = score;
    }
 
    public string Name
    {
      get { return name; }
    }
 
    public string Score
    {
      get { return score; }
    }
 
    public override string ToString()
    {
      return String.Format("姓名:{0},分數(shù):{1}", name, score);
    }
  }
 

運行結果如下圖所示:

由此可見,我們無法修改Student的其中某一個成員,只能通過構造函數(shù)創(chuàng)建一個新對象,滿足"對象的原子性"。
而且也無法修改Student對象實例的某個屬性值,符合"對象的常量性"。

3.如果有引用類型字段和屬性,如何做到"不可變性"?

  class Program
  {
    static void Main(string[] args)
    {
      string[] classes = {"語文", "數(shù)學"};
      Student student = new Student("張三", "85", classes);
      Console.WriteLine("==修改之前==");
      Console.WriteLine(student.ToString());
 
      string[] tempArray = student.Classes;
      tempArray[0] = "英語";
      Console.WriteLine("==修改之后==");
      Console.WriteLine(student.ToString());
      Console.ReadKey();
    }
  }
 
  public struct Student
  {
    private readonly string name;
    private readonly string score;
    private readonly string[] classes;
 
    public Student(string name, string score, string[] classes)
    {
      this.name = name;
      this.score = score;
      this.classes = classes;
    }
 
    public string Name
    {
      get { return name; }
    }
 
    public string Score
    {
      get { return score; }
    }
 
    public string[] Classes
    {
      get { return classes; }
    }
 
    public override string ToString()
    {
      string temp = string.Empty;
      foreach (string item in classes)
      {
        temp += item + ",";
      }
 
      return String.Format("姓名:{0},總分:{1},參加的課程有:{2}", name, score,temp.Substring(0, temp.Length -1));
    }
  }
 

結果如下圖所示:

由此可見,還是可以對對象的屬性間接修改賦值,不滿足不可變類型的"常量性"特點。

4.通過在構造函數(shù)和屬性的get訪問器中復制的方式來滿足不可變性

  class Program
  {
    static void Main(string[] args)
    {
      string[] classes = {"語文", "數(shù)學"};
      Student student = new Student("張三", "85", classes);
      Console.WriteLine("==修改之前==");
      Console.WriteLine(student.ToString());
 
      string[] tempArray = student.Classes;
      tempArray[0] = "英語";
      Console.WriteLine("==修改之后==");
      Console.WriteLine(student.ToString());
      Console.ReadKey();
    }
  }
 
  public struct Student
  {
    private readonly string name;
    private readonly string score;
    private readonly string[] classes;
 
    public Student(string name, string score, string[] classes)
    {
      this.name = name;
      this.score = score;
      this.classes = new string[classes.Length];
      classes.CopyTo(this.classes, 0);
      CheckScore(score);
    }
 
    public string Name
    {
      get { return name; }
    }
 
    public string Score
    {
      get { return score; }
    }
 
    public string[] Classes
    {
      get
      {
        string[] result = new string[classes.Length];
        classes.CopyTo(result,0);
        return result;
      }
    }
 
    //檢測分數(shù)是否是2位數(shù)整數(shù)
    private void CheckScore(string value)
    {
      string pattern = @"\d{2}";
      if (!Regex.IsMatch(value, pattern))
      {
        throw new Exception("不是有效分數(shù)!");
      }
    }
 
    public override string ToString()
    {
      string temp = string.Empty;
      foreach (string item in classes)
      {
        temp += item + ",";
      }
 
      return String.Format("姓名:{0},總分:{1},參加的課程有:{2}", name, score,temp.Substring(0, temp.Length -1));
    }
  }
 

運行結果如下圖所示:

此外,如果讓分數(shù)不滿足條件,Student student = new Student("張三", "8", classes),就會報錯:

相關文章

  • WPF實現(xiàn)數(shù)據(jù)綁定的幾種方法

    WPF實現(xiàn)數(shù)據(jù)綁定的幾種方法

    Windows Presentation Foundation (WPF) 是微軟開發(fā)的一套用于構建用戶界面的框架,在 WPF 中,數(shù)據(jù)綁定是一個非常重要的概念,它使得 UI 和數(shù)據(jù)源之間的同步變得簡單和高效,本文將詳細分析 WPF 中實現(xiàn)數(shù)據(jù)綁定的幾種方法,需要的朋友可以參考下
    2024-12-12
  • C# 的析構以及垃圾回收實例分析

    C# 的析構以及垃圾回收實例分析

    這篇文章主要介紹了C# 的析構以及垃圾回收實例分析的相關資料,需要的朋友可以參考下
    2017-06-06
  • C#圖片處理3種高級應用

    C#圖片處理3種高級應用

    本文介紹C#圖片處理高級應用,這些功能并無多大技術含量。全部基于.Net Framework類庫完成,代碼中包含了C#圖片處理的一些基礎知識,與大家分享,個人能力有限,不足之處還請及時指正。
    2015-10-10
  • c#對XML文檔的創(chuàng)建與增刪改查的示例代碼

    c#對XML文檔的創(chuàng)建與增刪改查的示例代碼

    這篇文章主要介紹了c#對XML文檔的創(chuàng)建與增刪改查的示例代碼,文中講解非常細致,幫助大家更好的理解和學習,感興趣的朋友可以了解下
    2020-07-07
  • C#遍歷操作系統(tǒng)下所有驅(qū)動器的方法

    C#遍歷操作系統(tǒng)下所有驅(qū)動器的方法

    這篇文章主要介紹了C#遍歷操作系統(tǒng)下所有驅(qū)動器的方法,涉及C#中DriveInfo類GetDrivers方法的使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-04-04
  • c#中Empty()和DefalutIfEmpty()用法分析

    c#中Empty()和DefalutIfEmpty()用法分析

    這篇文章主要介紹了c#中Empty()和DefalutIfEmpty()用法,以實例形式分析了針對不同情況下Empty()和DefalutIfEmpty()用法區(qū)別,需要的朋友可以參考下
    2014-11-11
  • Unity3D移動端實現(xiàn)搖一搖功能

    Unity3D移動端實現(xiàn)搖一搖功能

    這篇文章主要為大家詳細介紹了基于Unity3D移動端實現(xiàn)搖一搖功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • C#不可變類型深入解析

    C#不可變類型深入解析

    這篇文章主要介紹了C#不可變類型,對于C#程序員深入理解string數(shù)據(jù)類型有很大的幫助,需要的朋友可以參考下
    2014-08-08
  • C#清除字符串內(nèi)空格的方法

    C#清除字符串內(nèi)空格的方法

    這篇文章主要介紹了C#清除字符串內(nèi)空格的方法,是C#操作字符串非常實用的技巧,需要的朋友可以參考下
    2014-10-10
  • WinForm天貓雙11自動搶紅包源碼分享

    WinForm天貓雙11自動搶紅包源碼分享

    這篇文章主要為大家分享了WinForm天貓雙11自動搶紅包源碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10

最新評論

通化市| 金塔县| 彰化市| 长泰县| 沁阳市| 手游| 女性| 灌南县| 金山区| 南康市| 正镶白旗| 钟祥市| 合水县| 凤冈县| 湟源县| 镇巴县| 会宁县| 阿拉尔市| 西丰县| 永平县| 白水县| 年辖:市辖区| 陆河县| 孝感市| 维西| 五华县| 锡林浩特市| 秀山| 亚东县| 衡东县| 肇州县| 盐亭县| 湖州市| 隆林| 新昌县| 桑日县| 衡东县| 那曲县| 尉氏县| 临桂县| 青阳县|