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

C#入門學習之集合、比較和轉換

 更新時間:2022年05月05日 10:11:16   作者:springsnow  
本文詳細講解了C#中的集合、比較和轉換,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

一、集合

C#中的數組是作為System.Array類的實例來執(zhí)行的,它們是集合類中的一種。 
集合類一般用于處理對象列表,其功能是通過執(zhí)行System.Collection中的接口實現的。

集合的功能可以通過接口來實現,該接口可以使用基本基本集合類,也可以創(chuàng)建自定義的集合類。

System.Collections 命名空間有很多接口提供了基本的集合功能:

  • IEnumerable:公開枚舉數,該枚舉數支持在非泛型集合上進行簡單迭代
  • ICollection:定義所有非泛型集合的大小、枚舉數和同步方法
  • IList:表示可按照索引單獨訪問的對象的非泛型集合
  • IDictionary:表示鍵/值對的非通用集合

System.Array類繼承了IList,ICollection和IEnumerable。但不支持IList的一些高級功能,而且是一個大小固定的項目列表。

1、使用集合

Systems.Collections中的一個類System.Collections.ArrayList,也執(zhí)行IList,ICollection和IEnumerable接口,但與數組不同,它是大小可變的 
使用System.Array類的集合(數組),必須用固定的大小來初始化數組 
例如:

Animal[] animalArray = new Animal[2];

使用System.ArrayList類的集合,不需要初始化其大小 
例如:

ArrayList animalArrayList = new ArrayList();

這個類還有兩個構造函數: 
1 把現有集合作為參數復制到新實例中 
2 用一個int參數設置集合的容量,不過實際內容超過容量時會自動增加 
初始化數組,需要給這個項目賦予初始化了的對象 
例如:

Cow myCow1 = new Cow("Deirdre");
animalArray[0] = myCow1;
animalArray[1] = new Chicken("Ken");

可以用這兩種方式初始化數組

對于ArrayList集合,需要用Add()方法添加新項目 
例如:

Cow myCow2 = new Cow("Hayley");
animalArrayList.Add(myCow2);
animalArrayList.Add(new Chicken("Roy"));

在添加萬項目之后,就可以用與數組相同的語法重寫他們 
例如:

animalArrayList[1] = new Chicken("Roy2")

Array數組和ArrayList集合都支持foreach結構來迭代 
例如:

foreach (Animal myAnimal in animalArray)
{
}

foreach (Animal myAnimal in animalArrayList)
{
}

Array數組使用Length屬性獲取項目的個數 
例如:

int animalCount = animalArray.Length;

ArrayList集合使用Count屬性獲取項目的個數

int animalCount2 = animalArrayList.Count;

Array數組是強類型化的,可以直接使用數組的類型來存儲項目 
即可以直接訪問項目的屬性和方法 
例如: 
對于類型是Animal的數組,Feed()是類Animal的方法

animalArray[0].Feed();

但對于類Animal派生類的方法,就不能直接調用,需要強制轉換

((Chicken)animalArray[1]).LayEgg();

ArrayList集合是System.Object對象的集合,通過多態(tài)性賦給Animal對象 
必須進行數據類型轉換 
例如:

((Animal)animalArrayList[0]).Feed();
((Chicken)animalArrayList[1]).LayEgg();

使用Remove()和RemoveAt()方法刪除項目 
Remove  從 ArrayList 中移除特定對象的第一個匹配項(參數為特定對象) 
RemoveAt 移除 ArrayList 的指定索引處的元素(參數為索引值) 
刪除項目后,會使其他項目在數組中移動一個位置

使用AddRange()和InsertRange()方法可以一次添加多個項目 
AddRange 將 ICollection 的元素添加到 ArrayList 的末尾 
InsertRange 將集合中的某個元素插入 ArrayList 的指定索引處。 
例如:

animalArrayList.AddRange(animalArray);

使用IndexOf()方法獲取指定項目的索引值 
IndexOf 返回 ArrayList 或它的一部分中某個值的第一個匹配項的從零開始的索引。  
可以通過索引值直接訪問選項 
例如:

int iIndex =  animalArrayList.IndexOf(myCow1);
((Animal)animalArrayList[iIndex]).Feed();

2、自定義集合

可以從一個類派生自定義的集合 
推薦使用System.Collections.CollectionBase類。CollectionBase類有接口IEnumerable,ICollection,和IList

List屬性可以通過Ilist接口訪問項目,InnerList屬性用于存儲項目的ArrayList對象

例如:

public class Animals : CollectionBase
 {
    public void Add(Animal newAnimal)
    {
        List.Add(newAnimal);
    }

    public void Remove(Animal oldAnimal)
    {
        List.Remove(oldAnimal);
    }

    public Animals()
    {
    }
 }

這個類用于生成Animal類型的集合,可以用foreach訪問其成員:

Animals animalCollection = new Animals();
animalCollection.Add(new Cow("Sarah"));
foreach (Animal myAnimal in animalCollection)
{
}

如果要以索引的方式訪問項目,就需要使用索引符

3、索引符

索引符是一種特殊類型的屬性,可以把它添加到類中,提供類似數組的訪問。 
最常見的一個用法是對項目執(zhí)行一個數字索引

例如: 
在Animals集合中添加一個索引符

public class Animals : CollectionBase
{
     ...
     public Animal this[int animalIndex]
     {
         get
         {
             return (Animal)List[animalIndex];
         }
         set
         {
             List[animalIndex] = value;
         }
     }
 }

this關鍵字與方括號一起,方括號中是索引參數 
對List使用一個索引符,而且顯示聲明了類型,因為IList接口返回的是System.Object對象 
現在可以用索引的方式訪問項目:

animalCollection[0].Feed();

4、關鍵字值集合和IDictionary

集合還可以執(zhí)行類似的IDictionary接口,通過關鍵字值進行索引 
使用基類DictionaryBase,它也執(zhí)行IEnumerable和ICollection接口,提供了對任何集合都相同的集合處理功能

例如:

public class Animals : DictionaryBase
 {
    public void Add(string newID, Animal newAnimal)
    {
        Dictionary.Add(newID, newAnimal);
    }

    public void Remove(string animalID)
    {
        Dictionary.Remove(animalID);
    }

    public Animals()
    {
    }

    public Animal this[string animalID]
    {
        get
        {
            return (Animal)Dictionary[animalID];
        }
        set
        {
            Dictionary[animalID] = value;
        }
    }
}

這樣添加了Add()方法,Remove()方法和一個通過關鍵字訪問項目的方法 
其中Dictionary是包含在DictionaryBase實例中的元素的列表

DictionaryBase集合和CollectionBase集合在foreach的工作方式不同, 
DictionaryBase提供的是DictionaryEntry結構,需要通過Value成員獲取對象本身 
例如: 
CollectionBase集合:

foreach (Animal myAnimal in animalCollection)
{
    myAnimal.Feed();
}

DictionaryBase集合:

foreach (DictionaryEntry myEntry in animalCollection)
{
    ((Animal)myEntry.Value).Feed();
}

5、迭代器

通過IEnumerable接口,可以使用foreach循環(huán)獲取對象 
foreach循環(huán),迭代collectionObject的過程: 
1 調用Collection的GetEnumerator()方法返回一個IEnumerator引用 
   該方法也可以通過IEnumerable接口的實現代碼獲得 
2 調用IEnumerator接口的MoveNext()方法,將枚舉數推進到集合的下一個元素 
3 如果MoveNext()方法返回true,使用IEnumerator接口的Current屬性獲取對象的引用,用于foreach循環(huán) 
4 重復前兩個步驟,直至MoveNext()返回false時,循環(huán)停止

迭代器是一個按順序提供要在foreach循環(huán)中使用的所有值的代碼塊 
一般這個代碼塊是一個方法,也可以使用屬性訪問器和其他代碼塊作為迭代器 
代碼塊的返回值可能是IEnumerable或IEnumerator接口類型: 
1 如果要迭代一個類,可使用方法IEnumerator(),其返回類型是IEnumerator 
2 如果要迭代一個類成員,則使用IEnumerable

在迭代器塊中,使用yield關鍵字選擇要在foreach循環(huán)中使用的值 
語法:

yield return value;

例如:

public static IEnumerable SimpleList()
{
    yield return "string 1";
    yield return "string 2";
    yield return "string 3";
}

public static void Main(string[] args)
{
    foreach (string item in SimpleList())
    Console.WriteLine(item);

    Console.ReadKey();
}

這里SimpleList就是迭代器塊,是一個方法,使用IEnumerable返回類型 
可以從yield語句中返回任意類型

可以中斷信息返回foreach循環(huán)過程 
語法:yield break;

6、迭代器和集合

迭代器可以用于迭代儲存在目錄類型的集合中的對象 
例如:

public new IEnumerator GetEnumerator()
{
    foreach (object animal in Dictionary.Values)
    yield return (Animal)animal;
}

迭代集合中的對象:

foreach (Animal myAnimal in animalCollection)
{
}

7、深度復制

使用System.Object.MemberwiseClone()方法可以進行陰影復制 
對于值類型成員,沒什么問題 
但對于引用類型成員,新對象和源對象的成員將指向同一個引用對象 
例如:

public class Content
{
    public int Val;
}
    
public class Cloner
{
    public Content MyContent = new Content();
    
    public Cloner(int newVal)
    {
        MyContent.Val = newVal;
    }

    public object GetCopy()
    {
        return MemberwiseClone();
    }
}

執(zhí)行:

Cloner mySource = new Cloner(5);
Cloner myTarget = (Cloner)mySource.GetCopy();
int iVal1 = myTarget.MyContent.Val;
mySource.MyContent.Val = 2;
int iVal2 = myTarget.MyContent.Val;

結果: 
iVal1是5,iVal2是2

但有時候需要的是分別引用各自的對象,使用深度復制就可以解決 
標準方式是添加一個ICloneable接口,該接口有一個Clone()方法 
該方法不帶參數,返回一個對象類型 
例如:

public class Content
{
    public int Val;
}
    
public class Cloner : ICloneable
{
    public Content MyContent = new Content();
    public int iVal = 0;
    
    public Cloner(int newVal)
    {
        MyContent.Val = newVal;
    }
    
    public object Clone()
    {
        Cloner clonedCloner = new Cloner(MyContent.Val);
        clonedCloner.iVal = iVal;
        return clonedCloner;
    }
}

通過Cloner對象的Val字段創(chuàng)建一個相同的Cloner對象 
如果有值成員需要復制,那必須給新對象添加上這個成員 
這樣就能復制一個與源對象相同而互相獨立的新對象

用GetCopy換成Clone,執(zhí)行相同的程序,結果: 
iVal1是5,iVal2是5

二、比較

1、類型比較

比較對象時,需要先知道對象的類型,可以使用GetType()方法 
配合typeof()運算符一起使用,就可以確定對象的類型

if (myObj.GetType() == typeof(MyComplexClass))
{
    // myObj is an instance of the class MyComplexClass.
}

封箱和拆箱

處理值類型時后臺的操作: 
封箱(boxing)是把值類型轉換為System.Object類型或由值類型實現的接口類型 
拆箱(unboxing)是相反的過程 
例如: 
結構類型:

struct MyStruct
{
    public int Val;
}

把類型結構放在object類型變量中封箱:

MyStruct valType1 = new MyStruct();
valType1.Val = 5;
object refType = valType1;

這里創(chuàng)建了一個MyStruct類型的valType1,給成員賦值后封箱到對象refType中 
這種方式的封裝,將包含值類型的一個副本的引用,而不是源值的引用 
驗證:

valType1.Val = 6;
MyStruct valType2 = (MyStruct)refType;

結果valType2.Val是5而不是6

如果對個引用類型進行封裝,將包含源值的引用 
例如:

class MyStruct
{
    public int Val;
}

執(zhí)行相同的操作,得到valType2.Val的值是6

可以把值類型封箱到一個接口類型中:

interface IMyInterface
{
}
struct MyStruct : IMyInterface
{
    public int Val;
}

把結構封箱到IMyInterface類型中:

MyStruct valType1 = new MyStruct();
IMyInterface refType = valType1;

拆箱:

MyStruct ValType2 = (MyStruct)refType;

封箱是在沒有用戶干涉的情況下進行的 
拆箱一個值需要進行顯式轉換(封箱是隱式的轉換) 
訪問值類型的內容前,必須進行拆箱

is運算符

is運算符可以檢查對象是否是給定的類型,或者是否可以轉換為給定的類型 
語法:

is

1 如果是一個類類型,也是該類型,或繼承了該類型,或封箱到該類型中,則返回true 
2 如果是一個接口類型,也是該類型,或是實現該接口的類型,則返回true 
3 如果是一個值類型,也是該類型,或封箱到該類型中,則返回true

2、值比較

運算符重載

要重載運算符,可給類添加運算符類型成員(必須是static) 
例如: 
重載+運算符:

public class AddClass1
{
    public int val;

    public static AddClass3 operator +(AddClass1 op1, AddClass2 op2)
    {
        AddClass3 returnVal = new AddClass3();
        returnVal.val = op1.val + op2.val;
        return returnVal;
    }
}

public class AddClass2
{
    public int val;
}

public class AddClass3
{
    public int val;
}

運算符重載與標準靜態(tài)方法聲明類似,但它使用關鍵字operator和運算符本身 
使用:

AddClass1 op1 = new AddClass1();
op1.val = 5;
AddClass2 op2 = new AddClass2();
op2.val = 4;
AddClass3 op3 = op1 + op2;

結果op3.val的值是9

注意:如果混合了類型,操作數數序必須與運算符重載參數順序相同

可以重載的運算符: 
一元運算符:+,-,!,~,++,--,true,false 
二元運算符:+,-,*,/,%,&,|,^,<<,>> 
比較運算符:==,!=,<,>,<=,>= 
注意: 
如果重載true或false運算符,可以在布爾表達式中使用類,例如if (op1) {}

運算符如 < 和 > 必須成對重載,但可以使用其他運算符來減少代碼 
例如:

class Addclass1
{
    public int val;

    public static bool operator >=(Addclass1 op1, Addclass2 op2)
    {
        return op1.val >= op2.val;
    }

    public static bool operator <(Addclass1 op1, Addclass2 op2)
    {
        return !(op1>= op2);
    }

    public static bool operator <=(Addclass1 op1, Addclass2 op2)
    {
        return op1.val <= op2.val;
    }

    public static bool operator >(Addclass1 op1, Addclass2 op2)
    {
        return !(op1 <= op2);
    }
}

同時適用于==和!=,常常需要重寫Object.Equals()和Object.GetHashCode()

class Addclass1
{
    public int val;

    public static bool operator ==(Addclass1 op1, Addclass1 op2)
    {
        return (op1.val == op2.val);
    }

    public static bool operator !=(Addclass1 op1, Addclass1 op2)
    {
        return !(op1== op2);
    }

    public override bool Equals(object obj)
    {
        return val == ((Addclass1)obj).val;
    }

    public override int GetHashCode()
    {
        return val;
    }
}

IComparable和IComparer接口

IComparable和IComparer接口是比較對象的標準方式 
區(qū)別: 
IComparable在要比較的對象的類中實現,可以比較該對象和另一個對象 
IComparer在一個單獨的類中實現,可以比較任意兩個對象

.Net Framework 在類Comparer上提供了IComparer接口的默認實現方式,類Comparer位于System.Collections命名空間中,可以對簡單類型以及支持IComparable接口的任意類型進行特定文化的比較

public class SamplesComparer
{
    public static void Main()
    {
        String str1 = "llegar";
        String str2 = "lugar";
        Console.WriteLine("Comparing \"{0}\" and \"{1}\" ", str1, str2);

        // Uses the DefaultInvariant Comparer.
        Console.WriteLine("   Invariant Comparer: {0}", Comparer.DefaultInvariant.Compare(str1, str2));

        // Uses the Comparer based on the culture "es-ES" (Spanish - Spain, international sort).
        Comparer myCompIntl = new Comparer(new CultureInfo("es-ES", false));
        Console.WriteLine("   International Sort: {0}", myCompIntl.Compare(str1, str2))
    }
}

一般使用IComparable給出類的默認比較代碼,使用其他類給出非默認的比較代碼 
IComparable提供一個CompareTo()方法比較兩個對象,并返回一個int值 
例如:

class Person : IComparable
{
    public string Name;
    public int Age;

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }

    public int CompareTo(object obj)
    {
        if (obj is Person)
        {
            Person otherPerson = obj as Person;
            return this.Age - otherPerson.Age;
        }
        else
        {
            throw new ArgumentException( "Object to compare to is not a Person object.");
        }
    }
}

主程序代碼

class Program
{
    static void Main(string[] args)
    {
        Person person1 = new Person("Jim", 30);
        Person person2 = new Person("Bob", 25);

        if (person1.CompareTo(person2) == 0)
        {
            Console.WriteLine("Same age");
        }
        else if (person1.CompareTo(person2) > 0)
        {
            Console.WriteLine("person 1 is Older");
        }
        else
        {
            Console.WriteLine("person1 is Younger");
        }
    }
}

IComparer提供一個Compare()方法,接受兩個對象返回一個整型結果 
例如:

public class PersonComparer : IComparer
{
    public static IComparer Default = new PersonComparer();

    public int Compare(object x, object y)
    {
        if (x is Person && y is Person)
        {
            return Comparer.Default.Compare(((Person)x).Age, ((Person)y).Age);
        }
        else
        {
            throw new ArgumentException(
            "One or both objects to compare are not Person objects.");
        }
    }
}

主程序:

class Program
{
    static void Main(string[] args)
    {
        Person person1 = new Person("Jim", 30);
        Person person2 = new Person("Bob", 25);

        if (PersonComparer.Default.Compare(person1, person2) == 0)
        {
            Console.WriteLine("Same age");
        }
        else if (PersonComparer.Default.Compare(person1, person2) > 0)
        {
            Console.WriteLine("person 1 is Older");
        }
        else
        {
            Console.WriteLine("person1 is Younger");
        }
    }
}

三、轉換

1、重載轉換運算符

implicit 關鍵字用于聲明隱式的用戶定義類型轉換運算符 
explicit 關鍵字用于聲明顯式的用戶定義類型轉換運算符

例如:

public class ConvClass1
{
    public int val;

    public static implicit operator ConvClass2(ConvClass1 op1)
    {
        ConvClass2 returnVal = new ConvClass2();
        returnVal.val = op1.val.ToString();
        return returnVal;
    }
}

public class ConvClass2
{
    public string val;

    public static explicit operator ConvClass1(ConvClass2 op1)
    {
        ConvClass1 returnVal = new ConvClass1();
        returnVal.val = Convert.ToInt32(op1.val);
        return returnVal;
    }
}

使用:

ConvClass1 op1 = new ConvClass1();
op1.val = 5;
ConvClass2 op2 = op1;

這里使用了隱式轉換,此時op2.val的值是字符"5"

ConvClass2 op1 = new ConvClass2();
op1.val = "6";
ConvClass1 op2 = (ConvClass1)op1;

這里使用了顯示轉換,此時op2.val的值是數字6

2、as運算符

as運算符可以把一種類型轉換為指定的引用類型 
語法:

as

只適用于: 
1 的類型是類型 
2 可以隱式轉換為類型 
3 可以封箱到類型中 
如果不能從轉換為,則表達式結果是null

例如: 

class ClassA : IMyInterface
{
}
    
class ClassD : ClassA
{
}

ClassA obj1 = new ClassA();
ClassD obj2 = obj1 as ClassD;

obj2的結果是null

使用一般的類型轉換,出錯時會拋出一個異常 
而as只會把null賦給對象,只要判斷對象是否null就知道轉換是否成功。

到此這篇關于C#集合、比較和轉換的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • WPF如何繪制光滑連續(xù)貝塞爾曲線示例代碼

    WPF如何繪制光滑連續(xù)貝塞爾曲線示例代碼

    貝塞爾曲線,又稱貝茲曲線或貝濟埃曲線,一般的矢量圖形軟件通過它來精確畫出曲線,下面這篇文章主要給大家介紹了關于WPF如何繪制光滑連續(xù)貝塞爾曲線的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下。
    2018-04-04
  • C#全角半角轉換函數代碼分享

    C#全角半角轉換函數代碼分享

    這篇文章介紹了C#全角半角轉換函數代碼,有需要的朋友可以參考一下
    2013-09-09
  • C#如何自動識別文件的編碼

    C#如何自動識別文件的編碼

    相信每位程序員在日常學習工作中,文件編碼識別是必不可少的,一旦編碼錯誤就會出現讓人頭疼的亂碼,那么下面這篇文章將給大家介紹如何通過C#來自動識別文件的編碼。文中給出了詳細的示例代碼,對大家的理解很有幫助,下面跟著小編一起來學習學習吧。
    2016-12-12
  • C#實現事件總線的方法示例

    C#實現事件總線的方法示例

    事件總線是一種用于在應用程序內部或跨應用程序組件之間進行事件通信的機制,本文主要介紹了C#實現事件總線的方法示例,具有一定的參考價值,感興趣的可以了解一下
    2024-02-02
  • C#把EXCEL數據轉換成DataTable

    C#把EXCEL數據轉換成DataTable

    這篇文章介紹了C#把EXCEL數據轉換成DataTable的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04
  • C#實現將Email地址轉成圖片顯示的方法

    C#實現將Email地址轉成圖片顯示的方法

    這篇文章主要介紹了C#實現將Email地址轉成圖片顯示的方法,涉及C#操作圖片的相關技巧,需要的朋友可以參考下
    2015-06-06
  • 分享WCF聊天程序--WCFChat實現代碼

    分享WCF聊天程序--WCFChat實現代碼

    無意中在一個國外的站點下到了一個利用WCF實現聊天的程序,作者是:Nikola Paljetak。研究了一下,自己做了測試和部分修改,感覺還不錯,分享給大家
    2015-11-11
  • c# 圓形識別方案和直線識別方案的參考示例

    c# 圓形識別方案和直線識別方案的參考示例

    這篇文章主要介紹了c# 圓形識別方案和直線識別方案的實現示例,幫助大家更好的理解和學習使用c#,感興趣的朋友可以了解下
    2021-03-03
  • C#中yield return用法分析

    C#中yield return用法分析

    這篇文章主要介紹了C#中yield return用法,對比使用yield return與不使用yield return的流程,更直觀的分析了yield return的用法,需要的朋友可以參考下
    2014-09-09
  • C#使用GDI繪制直線的方法

    C#使用GDI繪制直線的方法

    這篇文章主要介紹了C#使用GDI繪制直線的方法,涉及C#中使用GDI繪圖的相關技巧,需要的朋友可以參考下
    2015-04-04

最新評論