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

淺談C#數組(二)

 更新時間:2021年09月23日 09:55:08   作者:Ruby_Lu  
上一篇文章我們介紹了C#數組的一部分,今天來個續(xù)文,關于C#數組想要了解更多的請看下面文章的具體內容

可以先了解上一篇文章內容C#數組(一)

一.枚舉集合

  在foreach語句中使用枚舉,可以迭代集合中的元素,且無需知道集合中元素的個數。foreach語句使用一個枚舉器。foreach會調用實現(xiàn)了IEnumerable接口的集合類中的GetEumerator()方法。GetEumerator()方法返回一個實現(xiàn)IEnumerator接口的對象枚舉。foreach語句就可以使用IEnumerable接口迭代集合了。
  GetEumerator()方法在IEnumerable接口中定義。

1.IEnumerator接口

  foreach語句使用IEnumerator接口的方法和屬性,迭代集合中所有元素。IEnumerator接口定義了Current屬性,來返回光標所在的元素,該接口的MoveNext()方法移動到集合的下一個元素上,如果有這個元素,該方法就返回true。如果集合不再有更多的元素,該方法就返回false.
  這個接口的泛型版本IEnumerator<T>派生自接口IDisposable,因此定義了Dispose()方法,來清理枚舉器占用的資源。

2.foreach語句

  C#中foreach語句不會解析為IL代碼中的foreach語句。C#編譯器會把foreach語句轉換為IEnumerator接口的方法和屬性。

  Person[] persons = {
    new Person { FirstName="Damon", LastName="Hill" },
    new Person { FirstName="Niki", LastName="Lauda" },
    new Person { FirstName="Ayrton", LastName="Senna" },
    new Person { FirstName="Graham", LastName="Hill" }
  };
  foreach (Person p in persons)
  {
    Console.WriteLine(p);
  }

  foreach語句會解析為下面的代碼:

  IEnumerator<Person> enumerator = persons.GetEumerator();
  while(enumerator.MoveNext())
  {
    Person p = enumerator.Current;
    Console.WriteLine(p);
  }

3.yield語句

  在C#2.0之前,foreach語句可以輕松的迭代集合,但創(chuàng)建枚舉器需要做大量的工作。C#2.0添加了yield語句,以便創(chuàng)建枚舉器。
  yield return 語句返回集合的一個元素,并移動到下一個元素。yield break可停止迭代。

下面的例子實現(xiàn)返回兩個字符串:

  public class HelloCollection
  {
    public IEnumerator<string> GetEnumerator()
    {
    yield return "Hello";
    yield return "World";
    }
  }


客戶端代碼:

  var helloCollection = new HelloCollection();
  foreach (string s in helloCollection)
  {
    Console.WriteLine(s);
  }

  包含yield語句的方法或屬性也稱為迭代塊。迭代塊必須聲明為返回IEnumeratorIEnumerable接口,或者這些接口的泛型版本。這個塊可以包含多條yield return語句或yield break語句,但不能包含return語句。

  使用迭代塊,編譯器會生成一個yield類型,其中包含一個狀態(tài)機,如下面代碼所示:
  yield類型實現(xiàn)IEnumeratorIDisposable接口的方法和屬性。下面的例子可以把yield類型看作內部類Enumerator。外部類的GetEnumerator()方法實例化并返回一個新的yield類型。在yield類型中,變量state定義了迭代的當前位置,每次調用MoveNext()時,當前位置都會改變。MoveNext()封裝了迭代塊的代碼,并設置了current變量的值,從而使Current屬性根據位置返回一個對象。

  public class HelloCollection
  {
    public IEnumerator<string> GetEnumerator()
    {
      return new Enumerator(0);
    }

  public class Enumerator:IEnumerator<string>,IEnumerator,IDisposable
  {
    private int state;
    private string current;

    public Enumerator(int state)
    {
      this.state = state;
    }

    bool System.Collections.IEnumerator.MoveNext()
    {
      switch(state)
      {
        case 0:
          current="hello";
          state =1;
          return true;
        case 1:
          current="world";
          state =2;
          return true;
        case 2:
          break;
      }

      return false;
    }

    void System.Collection>IEnumerator.Reset()
    {
      throw new NotSupportedException();
    }

    string System.Collections.Generic.IEnumerator<string>.Current
    {
      get
      {
        return current;
      }
    }

    object System.Collections.IEnumerator.Current
    {
      get
      {
        return current;
      }
    }

    void IDisposable.Dispose()
    {}
  }
}

  yield語句會產生一個枚舉器,而不僅僅生成一個包含的項的列表。這個枚舉器通過foreach語句調用。從foreach中依次訪問每一項,就會訪問枚舉器。這樣就可以迭代大量的數據,而無需一次把所有的數據都讀入內存。

(1).迭代集合的不同方式

    可以使用yield return語句,以不同方式迭代集合。
    類MusicTitles可以用默認方式通過GetEnumerator()方法迭代標題,該方法不必在代碼中編寫,也可以用Reverse()逆序迭代標題,Subset()方法迭代子集合:

   public class MusicTitles
    {
      string[] names = {
      "Tubular Bells", "Hergest Ridge",
      "Ommadawn", "Platinum" };

      public IEnumerator<string> GetEnumerator()
      {
        for (int i = 0; i < 4; i++)
        {
          yield return names[i];
        }
      }

      public IEnumerable<string> Reverse()
      {
        for (int i = 3; i >= 0; i--)
        {
          yield return names[i];
        }
      }

      public IEnumerable<string> Subset(int index, int length)
      {
        for (int i = index; i < index + length;i++)
        {
          yield return names[i];
        }
      }
    }

客戶端代碼:

    var titles = new MusicTitles();
    foreach (var title in titles)
    {
      Console.WriteLine(title);
    }
    Console.WriteLine();

    Console.WriteLine("reverse");
    foreach (var title in titles.Reverse())
    {
      Console.WriteLine(title);
    }
    Console.WriteLine();

    Console.WriteLine("subset");
    foreach (var title in titles.Subset(2, 2))
    {
      Console.WriteLine(title);
    }

(2).用yield return 返回枚舉器      

public class GameMoves
  {
    private IEnumerator cross;
    private IEnumerator circle;

    public GameMoves()
    {
      cross = Cross();
      circle = Circle();
    }

    private int move = 0;
    const int MaxMoves = 9;

    public IEnumerator Cross()
    {
      while (true)
      {
        Console.WriteLine("Cross, move {0}", move);
        if (++move >= MaxMoves)
          yield break;
        yield return circle;
      }
    }

    public IEnumerator Circle()
    {
      while (true)
      {
        Console.WriteLine("Circle, move {0}", move);
        if (++move >= MaxMoves)
          yield break;
        yield return cross;
      }
    }
  }

 

客戶端代碼:

   var game = new GameMoves();

    IEnumerator enumerator = game.Cross();
    while (enumerator.MoveNext())
    {
      enumerator = enumerator.Current as IEnumerator;
    }

這樣會交替調用Cross()Circle()方法。

二.元組(Tuple)

  元組可以合并不同類型的對象。元組起源于函數編程語言,如F#。在.NET Framework中,元組可用于所有的.Net語言。
  .NET Framework定義了8個泛型Tuple類和一個靜態(tài)Tuple類,它們用作元組的工廠。不同的泛型Tuple類支持不同數量的元素。如,Tuple<T1>包含一個元素,Tuple<T1,T2>包含兩個元素。

  Tuple<string, string> name = new Tuple<string, string>("Jochen", "Rindt");

元組也可以用靜態(tài)Tuple類的靜態(tài)Create()方法創(chuàng)建。Create()方法的泛型參數定了要實例化的元組類型:

  public static Tuple<int, int> Divide(int dividend, int divisor)
  {
    int result = dividend / divisor;
    int reminder = dividend % divisor;

    return Tuple.Create<int, int>(result, reminder);
  }

可以用屬性Item1和Item2訪問元組的項:

  var result = Divide(5, 2);
  Console.WriteLine("result of division: {0}, reminder: {1}", result.Item1, result.Item2);

  如果元組包含的項超過8個,就可以使用帶8個參數的Tuple類定義。最后一個模板參數是TRest,表示必須給它傳遞一個元組。這樣,就可以創(chuàng)建帶任意個參數的元組了。

  var tuple = Tuple.Create<string, string, string, int, int, int, double, Tuple<int, int>>(
  "Stephanie", "Alina", "Nagel", 2009, 6, 2, 1.37, Tuple.Create<int, int>(52, 3490));

三.結構比較

  數組和元組都實現(xiàn)接口IStructuralEquatable和IStructuralComparable。這兩個接口不僅可以比較引用,還可以比較內容。這些接口都是顯式實現(xiàn)的,所以在使用時需要把數組和元組強制轉換為這個接口。
  IStructuralEquatable接口用于比較兩個元組或數組是否有相同的內同,IStructuralComparable接口用于給元組或數組排序。

IStructuralEquatable接口示例:

  編寫實現(xiàn)IEquatable接口的Person類,IEquatable接口定義了一個強類型化的Equals()方法,比較FirstNameLastName的值:

   public class Person : IEquatable<Person>
  {
    public int Id { get; private set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public override string ToString()
    {
      return String.Format("{0}, {1} {2}", Id, FirstName, LastName);
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return base.Equals(obj);
        return Equals(obj as Person);
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }

    #region IEquatable<Person> Members

    public bool Equals(Person other)
    {
      if (other == null)
        return base.Equals(other);

      return this.FirstName == other.FirstName && this.LastName == other.LastName;
    }

    #endregion
  }

創(chuàng)建兩個包含相同內容的Person類型的數組:

  var janet = new Person { FirstName = "Janet", LastName = "Jackson" };
  Person[] persons1 = { new Person { FirstName = "Michael", LastName = "Jackson" }, janet };
  Person[] persons2 = { new Person { FirstName = "Michael", LastName = "Jackson" }, janet };


由于兩個變量引用兩個不同數組,所以!=返回True:

  if (persons1 != persons2)
    Console.WriteLine("not the same reference");

  對于IStructuralEquatable接口定義的Equals方法,第一個參數是object類型,第二個參數是IEqualityComparer類型。調用這個方法時,通過傳遞一個實現(xiàn)了EqualityComparer<T>的對象,就可以定義如何進行比較。通過EqualityComparer<T>類完成IEqualityComparer的一個默認實現(xiàn)。這個實現(xiàn)檢查T類型是否實現(xiàn)了IEquatable接口,并調用IEquatable.Equals()方法。如果該類沒有實現(xiàn)IEquatable接口,就調用Object基類中Equals()方法:

if ((persons1 as IStructuralEquatable).Equals(persons2, EqualityComparer<Person>.Default))
  {
    Console.WriteLine("the same content");
  }

元組示例:

Tuple<>類提供了兩個Epuals()方法:一個重寫了Object基類中的Epuals方法,并把object作為參數,第二個由IStructuralEquatable接口定義,并把object和IEqualityComparer作為參數。

  var t1 = Tuple.Create<int, string>(1, "Stephanie");
  var t2 = Tuple.Create<int, string>(1, "Stephanie");
  if (t1 != t2)
  Console.WriteLine("not the same reference to the tuple");

  這個方法使用EqualityComparer<object>.Default獲取一個ObjectEqualityComparer<object>,以進行比較。這樣就會調用Object.Equals()方法比較元組的每一項:

  if (t1.Equals(t2))
    Console.WriteLine("equals returns true");

還可以使用TupleComparer類創(chuàng)建一個自定義的IEqualityComparer

 TupleComparer tc = new TupleComparer();

  if ((t1 as IStructuralEquatable).Equals(t2, tc))
  {
    Console.WriteLine("yes, using TubpleComparer");
  }


  class TupleComparer : IEqualityComparer
  {
    #region IEqualityComparer Members

    public new bool Equals(object x, object y)
    {
      bool result = x.Equals(y);
      return result;
    }

    public int GetHashCode(object obj)
    {
      return obj.GetHashCode();
    }

    #endregion
  }

到此這篇關于淺談C#數組的文章就介紹到這了,更多相關C#數組內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C# 模擬瀏覽器并自動操作的實例代碼

    C# 模擬瀏覽器并自動操作的實例代碼

    這篇文章主要介紹了C# 模擬瀏覽器并自動操作的實例代碼,文中講解非常細致,幫助大家更好的理解和學習,感興趣的朋友可以了解下
    2020-07-07
  • C#實現(xiàn)身份證實名認證接口的示例代碼

    C#實現(xiàn)身份證實名認證接口的示例代碼

    身份證實名認證,即通過姓名和身份證號校驗個人信息的匹配程度,廣泛應用于金融、互聯(lián)網等多個領域,本文主要介紹了C#實現(xiàn)身份證實名認證接口的示例代碼,感興趣的可以了解一下
    2024-09-09
  • c#使用S22.Imap收劍靈激活碼郵件代碼示例(imap收郵件)

    c#使用S22.Imap收劍靈激活碼郵件代碼示例(imap收郵件)

    一個IMAP收發(fā)郵件的類庫S22.IMAP,方便易用,下面來個例子可以收劍靈激活碼郵件
    2013-12-12
  • 3種方法實現(xiàn)WindowsForm切換窗口

    3種方法實現(xiàn)WindowsForm切換窗口

    這篇文章主要介紹了3種方法實現(xiàn)WindowsForm切換窗口,文中講解非常詳細,示例代碼幫助大家更好的理解和學習,感興趣的朋友可以了解下
    2020-07-07
  • c# 圖片加密解密的實例代碼

    c# 圖片加密解密的實例代碼

    這篇文章介紹了c# 圖片加密解密的實例代碼,有需要的朋友可以參考一下
    2013-08-08
  • C#操作串口通信協(xié)議Modbus的常用方法介紹

    C#操作串口通信協(xié)議Modbus的常用方法介紹

    這篇文章介紹了C#操作串口通信協(xié)議Modbus的常用方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-05-05
  • 詳解C# FileStream類

    詳解C# FileStream類

    這篇文章主要介紹了詳解C# FileStream類的相關知識,文中講解的非常細致,代碼供大家參考和學習,感興趣的朋友可以了解下
    2020-06-06
  • C#操作注冊表的方法

    C#操作注冊表的方法

    以下從‘讀’‘寫’‘刪除’‘判斷’四個事例實現(xiàn)對注冊表的簡單操作
    2007-03-03
  • C#中的DataTable查詢實戰(zhàn)教程

    C#中的DataTable查詢實戰(zhàn)教程

    這篇文章主要介紹了C#中的DataTable查詢實戰(zhàn)教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • C#獲取屬性的displayName的3種方式

    C#獲取屬性的displayName的3種方式

    在C#中,獲取屬性的displayName可以通過多種方式實現(xiàn),包括使用特性、反射和LINQ,下面我將分別展示每種方法,并提供具體的示例代碼,感興趣的朋友可以參考下
    2024-07-07

最新評論