C#入門(mén)學(xué)習(xí)之集合、比較和轉(zhuǎn)換
一、集合
C#中的數(shù)組是作為System.Array類(lèi)的實(shí)例來(lái)執(zhí)行的,它們是集合類(lèi)中的一種。
集合類(lèi)一般用于處理對(duì)象列表,其功能是通過(guò)執(zhí)行System.Collection中的接口實(shí)現(xiàn)的。
集合的功能可以通過(guò)接口來(lái)實(shí)現(xiàn),該接口可以使用基本基本集合類(lèi),也可以創(chuàng)建自定義的集合類(lèi)。
System.Collections 命名空間有很多接口提供了基本的集合功能:
- IEnumerable:公開(kāi)枚舉數(shù),該枚舉數(shù)支持在非泛型集合上進(jìn)行簡(jiǎn)單迭代
- ICollection:定義所有非泛型集合的大小、枚舉數(shù)和同步方法
- IList:表示可按照索引單獨(dú)訪問(wèn)的對(duì)象的非泛型集合
- IDictionary:表示鍵/值對(duì)的非通用集合
System.Array類(lèi)繼承了IList,ICollection和IEnumerable。但不支持IList的一些高級(jí)功能,而且是一個(gè)大小固定的項(xiàng)目列表。
1、使用集合
Systems.Collections中的一個(gè)類(lèi)System.Collections.ArrayList,也執(zhí)行IList,ICollection和IEnumerable接口,但與數(shù)組不同,它是大小可變的
使用System.Array類(lèi)的集合(數(shù)組),必須用固定的大小來(lái)初始化數(shù)組
例如:
Animal[] animalArray = new Animal[2];
使用System.ArrayList類(lèi)的集合,不需要初始化其大小
例如:
ArrayList animalArrayList = new ArrayList();
這個(gè)類(lèi)還有兩個(gè)構(gòu)造函數(shù):
1 把現(xiàn)有集合作為參數(shù)復(fù)制到新實(shí)例中
2 用一個(gè)int參數(shù)設(shè)置集合的容量,不過(guò)實(shí)際內(nèi)容超過(guò)容量時(shí)會(huì)自動(dòng)增加
初始化數(shù)組,需要給這個(gè)項(xiàng)目賦予初始化了的對(duì)象
例如:
Cow myCow1 = new Cow("Deirdre");
animalArray[0] = myCow1;
animalArray[1] = new Chicken("Ken");可以用這兩種方式初始化數(shù)組
對(duì)于ArrayList集合,需要用Add()方法添加新項(xiàng)目
例如:
Cow myCow2 = new Cow("Hayley");
animalArrayList.Add(myCow2);
animalArrayList.Add(new Chicken("Roy"));在添加萬(wàn)項(xiàng)目之后,就可以用與數(shù)組相同的語(yǔ)法重寫(xiě)他們
例如:
animalArrayList[1] = new Chicken("Roy2")Array數(shù)組和ArrayList集合都支持foreach結(jié)構(gòu)來(lái)迭代
例如:
foreach (Animal myAnimal in animalArray)
{
}
foreach (Animal myAnimal in animalArrayList)
{
}Array數(shù)組使用Length屬性獲取項(xiàng)目的個(gè)數(shù)
例如:
int animalCount = animalArray.Length;
ArrayList集合使用Count屬性獲取項(xiàng)目的個(gè)數(shù)
int animalCount2 = animalArrayList.Count;
Array數(shù)組是強(qiáng)類(lèi)型化的,可以直接使用數(shù)組的類(lèi)型來(lái)存儲(chǔ)項(xiàng)目
即可以直接訪問(wèn)項(xiàng)目的屬性和方法
例如:
對(duì)于類(lèi)型是Animal的數(shù)組,F(xiàn)eed()是類(lèi)Animal的方法
animalArray[0].Feed();
但對(duì)于類(lèi)Animal派生類(lèi)的方法,就不能直接調(diào)用,需要強(qiáng)制轉(zhuǎn)換
((Chicken)animalArray[1]).LayEgg();
ArrayList集合是System.Object對(duì)象的集合,通過(guò)多態(tài)性賦給Animal對(duì)象
必須進(jìn)行數(shù)據(jù)類(lèi)型轉(zhuǎn)換
例如:
((Animal)animalArrayList[0]).Feed(); ((Chicken)animalArrayList[1]).LayEgg();
使用Remove()和RemoveAt()方法刪除項(xiàng)目
Remove 從 ArrayList 中移除特定對(duì)象的第一個(gè)匹配項(xiàng)(參數(shù)為特定對(duì)象)
RemoveAt 移除 ArrayList 的指定索引處的元素(參數(shù)為索引值)
刪除項(xiàng)目后,會(huì)使其他項(xiàng)目在數(shù)組中移動(dòng)一個(gè)位置
使用AddRange()和InsertRange()方法可以一次添加多個(gè)項(xiàng)目
AddRange 將 ICollection 的元素添加到 ArrayList 的末尾
InsertRange 將集合中的某個(gè)元素插入 ArrayList 的指定索引處。
例如:
animalArrayList.AddRange(animalArray);
使用IndexOf()方法獲取指定項(xiàng)目的索引值
IndexOf 返回 ArrayList 或它的一部分中某個(gè)值的第一個(gè)匹配項(xiàng)的從零開(kāi)始的索引。
可以通過(guò)索引值直接訪問(wèn)選項(xiàng)
例如:
int iIndex = animalArrayList.IndexOf(myCow1); ((Animal)animalArrayList[iIndex]).Feed();
2、自定義集合
可以從一個(gè)類(lèi)派生自定義的集合
推薦使用System.Collections.CollectionBase類(lèi)。CollectionBase類(lèi)有接口IEnumerable,ICollection,和IList
List屬性可以通過(guò)Ilist接口訪問(wèn)項(xiàng)目,InnerList屬性用于存儲(chǔ)項(xiàng)目的ArrayList對(duì)象
例如:
public class Animals : CollectionBase
{
public void Add(Animal newAnimal)
{
List.Add(newAnimal);
}
public void Remove(Animal oldAnimal)
{
List.Remove(oldAnimal);
}
public Animals()
{
}
}這個(gè)類(lèi)用于生成Animal類(lèi)型的集合,可以用foreach訪問(wèn)其成員:
Animals animalCollection = new Animals();
animalCollection.Add(new Cow("Sarah"));
foreach (Animal myAnimal in animalCollection)
{
}如果要以索引的方式訪問(wèn)項(xiàng)目,就需要使用索引符
3、索引符
索引符是一種特殊類(lèi)型的屬性,可以把它添加到類(lèi)中,提供類(lèi)似數(shù)組的訪問(wèn)。
最常見(jiàn)的一個(gè)用法是對(duì)項(xiàng)目執(zhí)行一個(gè)數(shù)字索引
例如:
在Animals集合中添加一個(gè)索引符
public class Animals : CollectionBase
{
...
public Animal this[int animalIndex]
{
get
{
return (Animal)List[animalIndex];
}
set
{
List[animalIndex] = value;
}
}
}this關(guān)鍵字與方括號(hào)一起,方括號(hào)中是索引參數(shù)
對(duì)List使用一個(gè)索引符,而且顯示聲明了類(lèi)型,因?yàn)镮List接口返回的是System.Object對(duì)象
現(xiàn)在可以用索引的方式訪問(wèn)項(xiàng)目:
animalCollection[0].Feed();
4、關(guān)鍵字值集合和IDictionary
集合還可以執(zhí)行類(lèi)似的IDictionary接口,通過(guò)關(guān)鍵字值進(jìn)行索引
使用基類(lèi)DictionaryBase,它也執(zhí)行IEnumerable和ICollection接口,提供了對(duì)任何集合都相同的集合處理功能
例如:
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()方法和一個(gè)通過(guò)關(guān)鍵字訪問(wèn)項(xiàng)目的方法
其中Dictionary是包含在DictionaryBase實(shí)例中的元素的列表
DictionaryBase集合和CollectionBase集合在foreach的工作方式不同,
DictionaryBase提供的是DictionaryEntry結(jié)構(gòu),需要通過(guò)Value成員獲取對(duì)象本身
例如:
CollectionBase集合:
foreach (Animal myAnimal in animalCollection)
{
myAnimal.Feed();
}DictionaryBase集合:
foreach (DictionaryEntry myEntry in animalCollection)
{
((Animal)myEntry.Value).Feed();
}5、迭代器
通過(guò)IEnumerable接口,可以使用foreach循環(huán)獲取對(duì)象
foreach循環(huán),迭代collectionObject的過(guò)程:
1 調(diào)用Collection的GetEnumerator()方法返回一個(gè)IEnumerator引用
該方法也可以通過(guò)IEnumerable接口的實(shí)現(xiàn)代碼獲得
2 調(diào)用IEnumerator接口的MoveNext()方法,將枚舉數(shù)推進(jìn)到集合的下一個(gè)元素
3 如果MoveNext()方法返回true,使用IEnumerator接口的Current屬性獲取對(duì)象的引用,用于foreach循環(huán)
4 重復(fù)前兩個(gè)步驟,直至MoveNext()返回false時(shí),循環(huán)停止
迭代器是一個(gè)按順序提供要在foreach循環(huán)中使用的所有值的代碼塊
一般這個(gè)代碼塊是一個(gè)方法,也可以使用屬性訪問(wèn)器和其他代碼塊作為迭代器
代碼塊的返回值可能是IEnumerable或IEnumerator接口類(lèi)型:
1 如果要迭代一個(gè)類(lèi),可使用方法IEnumerator(),其返回類(lèi)型是IEnumerator
2 如果要迭代一個(gè)類(lèi)成員,則使用IEnumerable
在迭代器塊中,使用yield關(guān)鍵字選擇要在foreach循環(huán)中使用的值
語(yǔ)法:
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就是迭代器塊,是一個(gè)方法,使用IEnumerable返回類(lèi)型
可以從yield語(yǔ)句中返回任意類(lèi)型
可以中斷信息返回foreach循環(huán)過(guò)程
語(yǔ)法:yield break;
6、迭代器和集合
迭代器可以用于迭代儲(chǔ)存在目錄類(lèi)型的集合中的對(duì)象
例如:
public new IEnumerator GetEnumerator()
{
foreach (object animal in Dictionary.Values)
yield return (Animal)animal;
}迭代集合中的對(duì)象:
foreach (Animal myAnimal in animalCollection)
{
}7、深度復(fù)制
使用System.Object.MemberwiseClone()方法可以進(jìn)行陰影復(fù)制
對(duì)于值類(lèi)型成員,沒(méi)什么問(wèn)題
但對(duì)于引用類(lèi)型成員,新對(duì)象和源對(duì)象的成員將指向同一個(gè)引用對(duì)象
例如:
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;
結(jié)果:
iVal1是5,iVal2是2
但有時(shí)候需要的是分別引用各自的對(duì)象,使用深度復(fù)制就可以解決
標(biāo)準(zhǔn)方式是添加一個(gè)ICloneable接口,該接口有一個(gè)Clone()方法
該方法不帶參數(shù),返回一個(gè)對(duì)象類(lèi)型
例如:
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;
}
}通過(guò)Cloner對(duì)象的Val字段創(chuàng)建一個(gè)相同的Cloner對(duì)象
如果有值成員需要復(fù)制,那必須給新對(duì)象添加上這個(gè)成員
這樣就能復(fù)制一個(gè)與源對(duì)象相同而互相獨(dú)立的新對(duì)象
用GetCopy換成Clone,執(zhí)行相同的程序,結(jié)果:
iVal1是5,iVal2是5
二、比較
1、類(lèi)型比較
比較對(duì)象時(shí),需要先知道對(duì)象的類(lèi)型,可以使用GetType()方法
配合typeof()運(yùn)算符一起使用,就可以確定對(duì)象的類(lèi)型
if (myObj.GetType() == typeof(MyComplexClass))
{
// myObj is an instance of the class MyComplexClass.
}封箱和拆箱
處理值類(lèi)型時(shí)后臺(tái)的操作:
封箱(boxing)是把值類(lèi)型轉(zhuǎn)換為System.Object類(lèi)型或由值類(lèi)型實(shí)現(xiàn)的接口類(lèi)型
拆箱(unboxing)是相反的過(guò)程
例如:
結(jié)構(gòu)類(lèi)型:
struct MyStruct
{
public int Val;
}把類(lèi)型結(jié)構(gòu)放在object類(lèi)型變量中封箱:
MyStruct valType1 = new MyStruct(); valType1.Val = 5; object refType = valType1;
這里創(chuàng)建了一個(gè)MyStruct類(lèi)型的valType1,給成員賦值后封箱到對(duì)象refType中
這種方式的封裝,將包含值類(lèi)型的一個(gè)副本的引用,而不是源值的引用
驗(yàn)證:
valType1.Val = 6; MyStruct valType2 = (MyStruct)refType;
結(jié)果valType2.Val是5而不是6
如果對(duì)個(gè)引用類(lèi)型進(jìn)行封裝,將包含源值的引用
例如:
class MyStruct
{
public int Val;
}執(zhí)行相同的操作,得到valType2.Val的值是6
可以把值類(lèi)型封箱到一個(gè)接口類(lèi)型中:
interface IMyInterface
{
}
struct MyStruct : IMyInterface
{
public int Val;
}把結(jié)構(gòu)封箱到IMyInterface類(lèi)型中:
MyStruct valType1 = new MyStruct(); IMyInterface refType = valType1;
拆箱:
MyStruct ValType2 = (MyStruct)refType;
封箱是在沒(méi)有用戶(hù)干涉的情況下進(jìn)行的
拆箱一個(gè)值需要進(jìn)行顯式轉(zhuǎn)換(封箱是隱式的轉(zhuǎn)換)
訪問(wèn)值類(lèi)型的內(nèi)容前,必須進(jìn)行拆箱
is運(yùn)算符
is運(yùn)算符可以檢查對(duì)象是否是給定的類(lèi)型,或者是否可以轉(zhuǎn)換為給定的類(lèi)型
語(yǔ)法:
is
1 如果是一個(gè)類(lèi)類(lèi)型,也是該類(lèi)型,或繼承了該類(lèi)型,或封箱到該類(lèi)型中,則返回true
2 如果是一個(gè)接口類(lèi)型,也是該類(lèi)型,或是實(shí)現(xiàn)該接口的類(lèi)型,則返回true
3 如果是一個(gè)值類(lèi)型,也是該類(lèi)型,或封箱到該類(lèi)型中,則返回true
2、值比較
運(yùn)算符重載
要重載運(yùn)算符,可給類(lèi)添加運(yùn)算符類(lèi)型成員(必須是static)
例如:
重載+運(yùn)算符:
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;
}運(yùn)算符重載與標(biāo)準(zhǔn)靜態(tài)方法聲明類(lèi)似,但它使用關(guān)鍵字operator和運(yùn)算符本身
使用:
AddClass1 op1 = new AddClass1(); op1.val = 5; AddClass2 op2 = new AddClass2(); op2.val = 4; AddClass3 op3 = op1 + op2;
結(jié)果op3.val的值是9
注意:如果混合了類(lèi)型,操作數(shù)數(shù)序必須與運(yùn)算符重載參數(shù)順序相同
可以重載的運(yùn)算符:
一元運(yùn)算符:+,-,!,~,++,--,true,false
二元運(yùn)算符:+,-,*,/,%,&,|,^,<<,>>
比較運(yùn)算符:==,!=,<,>,<=,>=
注意:
如果重載true或false運(yùn)算符,可以在布爾表達(dá)式中使用類(lèi),例如if (op1) {}
運(yùn)算符如 < 和 > 必須成對(duì)重載,但可以使用其他運(yùn)算符來(lái)減少代碼
例如:
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);
}
}同時(shí)適用于==和!=,常常需要重寫(xiě)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接口是比較對(duì)象的標(biāo)準(zhǔn)方式
區(qū)別:
IComparable在要比較的對(duì)象的類(lèi)中實(shí)現(xiàn),可以比較該對(duì)象和另一個(gè)對(duì)象
IComparer在一個(gè)單獨(dú)的類(lèi)中實(shí)現(xiàn),可以比較任意兩個(gè)對(duì)象
.Net Framework 在類(lèi)Comparer上提供了IComparer接口的默認(rèn)實(shí)現(xiàn)方式,類(lèi)Comparer位于System.Collections命名空間中,可以對(duì)簡(jiǎn)單類(lèi)型以及支持IComparable接口的任意類(lèi)型進(jìn)行特定文化的比較
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給出類(lèi)的默認(rèn)比較代碼,使用其他類(lèi)給出非默認(rèn)的比較代碼
IComparable提供一個(gè)CompareTo()方法比較兩個(gè)對(duì)象,并返回一個(gè)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提供一個(gè)Compare()方法,接受兩個(gè)對(duì)象返回一個(gè)整型結(jié)果
例如:
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");
}
}
}三、轉(zhuǎn)換
1、重載轉(zhuǎn)換運(yùn)算符
implicit 關(guān)鍵字用于聲明隱式的用戶(hù)定義類(lèi)型轉(zhuǎn)換運(yùn)算符
explicit 關(guān)鍵字用于聲明顯式的用戶(hù)定義類(lèi)型轉(zhuǎn)換運(yùn)算符
例如:
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;
這里使用了隱式轉(zhuǎn)換,此時(shí)op2.val的值是字符"5"
ConvClass2 op1 = new ConvClass2(); op1.val = "6"; ConvClass1 op2 = (ConvClass1)op1;
這里使用了顯示轉(zhuǎn)換,此時(shí)op2.val的值是數(shù)字6
2、as運(yùn)算符
as運(yùn)算符可以把一種類(lèi)型轉(zhuǎn)換為指定的引用類(lèi)型
語(yǔ)法:
as
只適用于:
1 的類(lèi)型是類(lèi)型
2 可以隱式轉(zhuǎn)換為類(lèi)型
3 可以封箱到類(lèi)型中
如果不能從轉(zhuǎn)換為,則表達(dá)式結(jié)果是null
例如:
class ClassA : IMyInterface
{
}
class ClassD : ClassA
{
}
ClassA obj1 = new ClassA();
ClassD obj2 = obj1 as ClassD;obj2的結(jié)果是null
使用一般的類(lèi)型轉(zhuǎn)換,出錯(cuò)時(shí)會(huì)拋出一個(gè)異常
而as只會(huì)把null賦給對(duì)象,只要判斷對(duì)象是否null就知道轉(zhuǎn)換是否成功。
到此這篇關(guān)于C#集合、比較和轉(zhuǎn)換的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
基于C#的電視臺(tái)節(jié)目表接口調(diào)用代碼
這篇文章主要介紹了基于C#的電視臺(tái)節(jié)目表接口調(diào)用代碼的相關(guān)資料,需要的朋友可以參考下2016-06-06
C#中一些你可能沒(méi)用過(guò)的調(diào)試窗口的方法
其他窗口比較常用,就不介紹了,是不是有一些你沒(méi)用到的窗口呢?2013-05-05
Unity中的InitializeOnLoad特性實(shí)踐深入解析
這篇文章主要為大家介紹了Unity中的InitializeOnLoad特性實(shí)踐深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
c# AES字節(jié)數(shù)組加密解密流程及代碼實(shí)現(xiàn)
這篇文章主要介紹了c# AES字節(jié)數(shù)組加密解密流程及代碼實(shí)現(xiàn),幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2020-11-11
C# 從Excel讀取數(shù)據(jù)向SQL server寫(xiě)入
這篇文章主要介紹了C# 從Excel讀取數(shù)據(jù)向SQL server寫(xiě)入的方法,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-03-03

