2021-07-13

C#集合相关知识

C#里面Collection下面ArrayList
1、动态数组 Array List:
动态数组(ArrayList)代表了可被单独索引的对象的有序集合。它基本上可以替代一个数组。但是,与数组不同的是,
您可以使用索引在指定的位置添加和移除项目,动态数组会自动重新调整它的大小。它也允许在列表中进行动态内存
分配、增加、搜索、排序各项。

表列出了 ArrayList 类的一些常用的 属性:

属性 描述
Capacity 获取或设置 ArrayList 可以包含的元素个数。
Count 获取 ArrayList 中实际包含的元素个数。
IsFixedSize 获取一个值,表示 ArrayList 是否具有固定大小。
IsReadOnly 获取一个值,表示 ArrayList 是否只读。
IsSynchronized 获取一个值,表示访问 ArrayList 是否同步(线程安全)。
Item[Int32] 获取或设置指定索引处的元素。
SyncRoot 获取一个对象用于同步访问 ArrayList。

1、public virtual int Add( object value );
在 ArrayList 的末尾添加一个对象。

2、public virtual void AddRange( ICollection c );
在 ArrayList 的末尾添加 ICollection 的元素。

3、public virtual void Clear();
从 ArrayList 中移除所有的元素。

4、public virtual bool Contains( object item );
判断某个元素是否在 ArrayList 中。

5、public virtual int IndexOf(object);
返回某个值在 ArrayList 中第一次出现的索引,索引从零开始。

6、public virtual void Insert( int index, object value );
在 ArrayList 的指定索引处,插入一个元素。

7、public virtual void InsertRange( int index, ICollection c );
在 ArrayList 的指定索引处,插入某个集合的元素。

8、public virtual void Remove( object obj );
从 ArrayList 中移除第一次出现的指定对象。

9、public virtual void RemoveAt( int index );
移除 ArrayList 的指定索引处的元素。

10、public virtual void RemoveRange( int index, int count );
从 ArrayList 中移除某个范围的元素。

11、public virtual void Reverse();
逆转 ArrayList 中元素的顺序。

12、public virtual void SetRange( int index, ICollection c );
复制某个集合的元素到 ArrayList 中某个范围的元素上。

13、public virtual void Sort();
对 ArrayList 中的元素进行排序。

14、public virtual void TrimToSize();
设置容量为 ArrayList 中元素的实际个数。

eg:
using System;
using System.Collections;

namespace CollectionApplication
{
class Program
{
static void Main(string[] args)
{
ArrayList al = new ArrayList();

        Console.WriteLine("Adding some numbers:");
        al.Add(45);
        al.Add(78);
        al.Add(33);
        al.Add(56);
        al.Add(12);
        al.Add(23);
        al.Add(9);
       
        Console.WriteLine("Capacity: {0} ", al.Capacity);   //结果:  Capacity: 8
        Console.WriteLine("Count: {0}", al.Count);    //结果: Count: 7
                 
        Console.Write("Content: ");
        foreach (int i in al)
        {
            Console.Write(i + " ");     //结果:Content : 45 78 33 56 12 23 9
        }
        Console.WriteLine();
        Console.Write("Sorted Content: ");
        al.Sort();
        foreach (int i in al)
        {
            Console.Write(i + " ");    //结果: Content: 9 12 23 33 45 56 78
        }
        Console.WriteLine();
        Console.ReadKey();
    }
}

}

C#里面Collection下面Queue(队列)
队列(Queue)代表了一个先进先出的对象集合。当您需要对各项进行先进先出的访问时,则使用队列。
当您在列表中添加一项,称为入队,当您从列表中移除一项时,称为出队。

下表列出了 Queue 类的一些常用的 属性:

属性 描述
Count 获取 Queue 中包含的元素个数。

Queue 类的一些常用的 方法:
1 public virtual void Clear();
从 Queue 中移除所有的元素。

2 public virtual bool Contains( object obj );
判断某个元素是否在 Queue 中。

3 public virtual object Dequeue();
移除并返回在 Queue 的开头的对象。

4 public virtual void Enqueue( object obj );
向 Queue 的末尾添加一个对象。

5 public virtual object[] ToArray();
复制 Queue 到一个新的数组中。

6 public virtual void TrimToSize();
设置容量为 Queue 中元素的实际个数。

eg:
using System;
using System.Collections;

namespace CollectionsApplication
{
class Program
{
static void Main(string[] args)
{
Queue q = new Queue();

     q.Enqueue('A');
     q.Enqueue('M');
     q.Enqueue('G');
     q.Enqueue('W');
     
     Console.WriteLine("Current queue: ");
     foreach (char c in q)
        Console.Write(c + " ");
     Console.WriteLine();
     q.Enqueue('V');
     q.Enqueue('H');
     Console.WriteLine("Current queue: ");        
     foreach (char c in q)
        Console.Write(c + " ");
     Console.WriteLine();
     Console.WriteLine("Removing some values ");
     char ch = (char)q.Dequeue();
     Console.WriteLine("The removed value: {0}", ch);
     ch = (char)q.Dequeue();
     Console.WriteLine("The removed value: {0}", ch);
     Console.ReadKey();
  }

}
}

结果:
Current queue:
A M G W
Current queue:
A M G W V H
Removing values
The removed value: A
The removed value: M

C#里面Collection下面SortedList
SortedList 类代表了一系列按照键来排序的键/值对,这些键值对可以通过键和索引来访问。
排序列表是数组和哈希表的组合。它包含一个可使用键或索引访问各项的列表。如果您使用索引访问各项,
则它是一个动态数组(ArrayList),如果您使用键访问各项,则它是一个哈希表(Hashtable)。集合中的
各项总是按键值排序。

下表列出了 SortedList 类的一些常用的 属性:

属性 描述
Capacity 获取或设置 SortedList 的容量。
Count 获取 SortedList 中的元素个数。
IsFixedSize 获取一个值,表示 SortedList 是否具有固定大小。
IsReadOnly 获取一个值,表示 SortedList 是否只读。
Item 获取或设置与 SortedList 中指定的键相关的值。
Keys 获取 SortedList 中的键。
Values 获取 SortedList 中的值。

1 public virtual void Add( object key, object value );
向 SortedList 添加一个带有指定的键和值的元素。

2 public virtual void Clear();
从 SortedList 中移除所有的元素。

3 public virtual bool ContainsKey( object key );
判断 SortedList 是否包含指定的键。

4 public virtual bool ContainsValue( object value );
判断 SortedList 是否包含指定的值。

5 public virtual object GetByIndex( int index );
获取 SortedList 的指定索引处的值。

6 public virtual object GetKey( int index );
获取 SortedList 的指定索引处的键。

7 public virtual IList GetKeyList();
获取 SortedList 中的键。

8 public virtual IList GetValueList();
获取 SortedList 中的值。

9 public virtual int IndexOfKey( object key );
返回 SortedList 中的指定键的索引,索引从零开始。

10 public virtual int IndexOfValue( object value );
返回 SortedList 中的指定值第一次出现的索引,索引从零开始。

11 public virtual void Remove( object key );
从 SortedList 中移除带有指定的键的元素。

12 public virtual void RemoveAt( int index );
移除 SortedList 的指定索引处的元素。

13 public virtual void TrimToSize();
设置容量为 SortedList 中元素的实际个数。

eg:
using System;
using System.Collections;

namespace CollectionsApplication
{
class Program
{
static void Main(string[] args)
{
SortedList sl = new SortedList();

     sl.Add("001", "Zara Ali");
     sl.Add("002", "Abida Rehman");
     sl.Add("003", "Joe Holzner");
     sl.Add("004", "Mausam Benazir Nur");
     sl.Add("005", "M. Amlan");
     sl.Add("006", "M. Arif");
     sl.Add("007", "Ritesh Saikia");

     if (sl.ContainsValue("Nuha Ali"))
     {
        Console.WriteLine("This student name is already in the list");   
     }
     else
     {
        sl.Add("008", "Nuha Ali");
     }

     // 获取键的集合
     ICollection key = sl.Keys;

     foreach (string k in key)
     {
        Console.WriteLine(k + ": " + sl[k]);
     }
  }

}
}
//注意,SortList会根据里面key值进行升序排序

结果:001: Zara Ali
002: Abida Rehman
003: Joe Holzner
004: Mausam Banazir Nur
005: M. Amlan
006: M. Arif
007: Ritesh Saikia
008: Nuha Ali

C#里面Collection下面Stack(栈)
堆栈(Stack)代表了一个后进先出的对象集合。当您需要对各项进行后进先出的访问时,则使用堆栈。
当您在列表中添加一项,称为推入元素,当您从列表中移除一项时,称为弹出元素。

下表列出了 Stack 类的一些常用的 属性:

属性 描述
Count 获取 Stack 中包含的元素个数。

下表列出了 Stack 类的一些常用的 方法:

序号 方法名 & 描述
1 public virtual void Clear();
从 Stack 中移除所有的元素。

2 public virtual bool Contains( object obj );
判断某个元素是否在 Stack 中。

3 public virtual object Peek();
返回在 Stack 的顶部的对象,但不移除它。

4 public virtual object Pop();
移除并返回在 Stack 的顶部的对象。

5 public virtual void Push( object obj );
向 Stack 的顶部添加一个对象。

6 public virtual object[] ToArray();
复制 Stack 到一个新的数组中。

eg:

using System;
using System.Collections;

namespace CollectionsApplication
{
class Program
{
static void Main(string[] args)
{
Stack st = new Stack();

        st.Push('A');
        st.Push('M');
        st.Push('G');
        st.Push('W');
       
        Console.WriteLine("Current stack: ");
        foreach (char c in st)
        {
            Console.Write(c + " ");
        }
        Console.WriteLine();
       
        st.Push('V');
        st.Push('H');
        Console.WriteLine("The next poppable value in stack: {0}",
        st.Peek());
        Console.WriteLine("Current stack: ");          
        foreach (char c in st)
        {
           Console.Write(c + " ");
        }
        Console.WriteLine();

        Console.WriteLine("Removing values ");
        st.Pop();
        st.Pop();
        st.Pop();
       
        Console.WriteLine("Current stack: ");
        foreach (char c in st)
        {
           Console.Write(c + " ");
        }
    }
}

}

结果:
Current stack:
W G M A
The next poppable value in stack: H
Current stack:
H V W G M A
Removing values
Current stack:
G M A

C#里面继承、接口、多态

C#里面接口、继承、多态

接口使用的注意事项:
1、接口方法不能用public abstract等修饰。接口内不能有字段变量,构造函数。
2、接口内可以定义属性(有get和set的方法)。如string color { get ; set ; }这种。
3、实现接口时,必须和接口的格式一致。
4、必须实现接口的所有方法。
5、接口中只能包含方法、属性、索引器和事件的声明。不允许声明成员上的修饰符,即使是pubilc都不行,
因为接口成员总是公有的,也不能声明为虚拟和静态的。如果需要修饰符,最好让实现类来声明。、
6、接口也可以彼此继承,就象类的继承一样。但是如果一个接口继承上一个接口的话,一样要继承上一个接口所有方法。
7、C#中的接口是独立于类来定义的。这与 C++模型是对立的,在 C++中接口实际上就是抽象基类。
8、接口可以定义方法、属性和索引。所以,对比一个类,接口的特殊性是:当定义一个类时,可以派生自多重接口,
而你只能可以从仅有的一个类派生。
9、一个接口定义一个只有抽象成员的引用类型。C#中一个接口实际所做的,仅仅只存在着方法标志,
但根本就没有执行代码。这就暗示了不能实例化一个接口,只能实例化一个派生自该接口的对象。

C#里面接口隔离
什么是接口隔离原理

根据一组方法,最好使用许多小接口来代替一个胖接口,每个小接口服务一个子模块

简单点说,客户端需要什么功能,就提供什么接口,对于客户端不需要的接口不应该强行要求其依赖;
类之间的依赖应该建立在最小的接口上面,这里最小的粒度取决于单一职责原则的划分。
自我理解就是将一个大接口的各个方法和属性细分到许多小接口,然后就可以根据实现类的需要选择相应的接口实现,
避免一个被实现接口中太多用不到的方法,还得被实现。

接口隔离之前
示例
public interface IProduct {
int ID { get; set; }
double Weight { get; set; }
int Stock { get; set; }
int Inseam { get; set; }
int WaistSize { get; set; }
}
public class Jeans : IProduct {
public int ID { get; set; }
public double Weight { get; set; }
public int Stock { get; set; }
public int Inseam { get; set; }
public int WaistSize { get; set; }
}
public class BaseballCap : IProduct {
public int ID { get; set; }
public double Weight { get; set; }
public int Stock { get; set; }
public int Inseam { get; set; }
public int WaistSize { get; set; }
public int HatSize { get; set; }
}

接口隔离后
示例
public interface IProduct {
int ID { get; set; }
double Weight { get; set; }
int Stock { get; set; }
}
public interface IPants {
int Inseam { get; set; }
int WaistSize { get; set; }
}
public interface IHat {
int HatSize { get; set; }
}
public class Jeans : IProduct, IPants {
public int ID { get; set; }
public double Weight { get; set; }
public int Stock { get; set; }
public int Inseam { get; set; }
public int WaistSize { get; set; }
}
public class BaseballCap : IProduct, IHat {
public int ID { get; set; }
public double Weight { get; set; }
public int Stock { get; set; }
public int HatSize { get; set; }
}

C#里面文件流

C#获得桌面绝对路径
可以使用Environment.SpecialFolder来获取当前用户的桌面路径
string desktopPath =Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
System.Environment类提供有关当前环境和平台的信息。
eg:
public static void Main(){
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); //如果要访问桌面文件加上+@"\文件名.txt";
Console.WriteLine($“Desktop Path: {desktopPath}”);
Console.ReadLine();
}

上面代码的输出是:
Desktop Path: C:\Users\UserName\Desktop

C#里面string类里面常用方法

1.ToArray() (ToCharArray())
ToCharArray (int startIndex, int length);
参数
startIndex
此实例内子字符串的起始位置。
length
此实例内子字符串的长度。

ToCharArray()用于将字符串变为字符数组。
eg: char[ ] arr=str.ToCharArray( );

2.Contains()
Contains (string value);
参数
value
要搜寻的字符串。
可判断字符中是否出现在字符串中,返回bool型
eg:
string name = “raoguang is a chinese!”;
string k = “”;
char[] chars = name.ToArray();
foreach (char a in chars)
{
if (!(k.Contains(a)))
{
k = k + a;
}
}
Console.WriteLine(k.ToString());
Console.ReadKey();

返回结果:raogun ische!

3.Insert()
Insert (int startIndex, string value);
参数
startIndex
插入的从零开始的索引位置。
value
要插入的字符串。
返回String 类型数据
eg:
string exam = “raoguang is a chinese!”;
string example = exam.Insert(8," and his family ");
Console.WriteLine(example);
Console.ReadKey();
返回结果:raoguang and his family is a chinese!

4.ToLower() ----(转化字符串为小写) ToUpper() ----(转化字符串为大写)
eg:
string a=“How are you”;
a=a.ToUpper(); //a=“HOW ARE YOU”;

5.IndexOf()
String.IndexOf 方法 (value, [startIndex], [count])
报告指定字符在此实例中的第一个匹配项的索引。搜索从指定字符位置开始,并检查指定数量的字符位置。
参数含义:
   value
  要查找的 Unicode 字符。 对 value 的搜索区分大小写。
   startIndex(Int32)
  可选项,搜索起始位置。不设置则从0开始。
   count(Int32)
  可选项,要检查的字符位数。
  返回值
  如果找到该字符,则为 value 的索引位置;否则如果未找到,则为 -1。
eg:
string exam = “raoguang is a chinese!”;
int position = exam.IndexOf(“c”);
Console.WriteLine(position);
Console.ReadKey();
返回结果:14

6.Substring()
截断字符串
eg:
string exam = “raoguang is a chinese!”;
string a = exam.Substring(3);
string b = exam.Substring(3,5);
Console.WriteLine(a);
Console.WriteLine(b);
Console.ReadKey();

返回结果:
guang is a chinese!
guang

7.Trim()
string strEscape = “\r;\n”;
strSrc = strSrc.Trim(strEscape.ToCharArray());
删除字符串头部和尾部的回车符。

C#中Trim()、TrimStart()、TrimEnd()的用法:
这三个方法用于删除字符串头尾出现的某些字符。
Trim()删除字符串头部及尾部出现的空格,删除的过程为从外到内,直到碰到一个非空格的字符为止,所以不管前后有多少个连续的空格都会被删除掉。
TrimStart()只删除字符串的头部的空格。
TrimEnd()只删除字符串尾部的空格。

如果这三个函数带上字符型数组的参数,则是删除字符型数组中出现的任意字符。
如Trim(“abcd”.ToCharArray())就是删除字符串头部及尾部出现的a或b或c或d字符,删除的过程直到碰到一个既不是a也不是b也不是c也不是d的字符才结束。
这里最容易引起的误会就是以为删除的是"abcd"字符串。
如下例:
string s = " from dual union all “;
s = s.Trim().TrimEnd(“union all”.ToCharArray());
ps:ToCharArray()是将字符串复制为字符数组
可能有人以为上面s的最终结果是"from dual”,
但真正的结果是"from d"。
需要注意的是这种写法执行的删除对象是字符数组中出现的任意字符,而不是这些字符连在一起组成的字符串!

eg:
string exam = " raoguang is a chinese ";
string a = exam.Trim();
Console.WriteLine(a);
string b = exam.TrimStart();
Console.WriteLine(b);
string c = exam.TrimEnd();
Console.WriteLine©;
string d = exam.Trim().TrimEnd(“chinese”.ToCharArray());
Console.WriteLine(d);
string e = exam.Trim().TrimStart(“chinese”.ToCharArray());
Console.WriteLine(e);
string f = exam.Trim(“chinese”.ToCharArray());
Console.WriteLine(f);
返回结果:
raoguang is a chinese
raoguang is a chinese
raoguang is a chinese
raoguang is a
raoguang is a chinese
raoguang is a chinese

8.Split()
将字符串划分为字符串数组
eg:
string exam = “how are you”;
string[] a = exam.Split(" ");
foreach (string b in a)
{
Console.WriteLine(b);
}
返回结果:
how
are
you

9.Replace()
Replace(Char, Char)
返回一个新字符串,其中此实例中出现的所有指定 Unicode 字符都替换为另一个指定的 Unicode 字符。
Replace(String, String)
返回一个新字符串,其中当前实例中出现的所有指定字符串都替换为另一个指定的字符串。
eg:
string exam = “how are you”;
string a = exam.Replace(" “,”|");
Console.WriteLine(a);
string b = exam.Replace(“are”,“do”);
Console.WriteLine(b);
返回结果:
how|are|you
how do you

10、String.Join 方法 (String, String[])
在指定 String 数组的每个元素之间串联指定的分隔符 String,从而产生单个串联的字符串。

eg:
string[] a = {“we are one”,“and you”,“what’s your mean?”};
string b = string.Join("-",a);
Console.WriteLine(b);
返回结果:
we are one-and you-what’s your mean?

11、public bool StartsWith( string value )
判断字符串实例的开头是否匹配指定的字符串。
eg:
string a = “a***b***c*d";
bool flag=a.StartsWith("a
"); //return true
bool flag=a.StartsWith("a
b”) //return false

12、public bool EndsWith( string value )
判断 string 对象的结尾是否匹配指定的字符串。
eg:
string a = “a***b***c***d”;
bool flag=a.StartsWith("**d"); //return true
bool flag=a.StartsWith("a
b") //return false

13、String.IsNullOrEmpty()方法
String.IsNullOrEmpty()方法是String类的内置方法,用于检查字符串是Null还是Empty
eg:
string str1="";
string str2=null;
string str3=" ";
string str4=“1112”;

bool flag=string.IsNullOrEmpty(str1); //true
bool flag=string.IsNullOrEmpty(str2); //true
bool flag=string.IsNullOrEmpty(str3); //false
bool flag=string.IsNullOrEmpty(str4); //false

C#里面反射

反射:用来操作元数据(metadata)的一个类库。(可以把反射当成一个小工具来读取或者操作元数据)

为什么要通过反射间接操作?
1、因为我们需要动态。
2、读取私有对象。

哪些地方用到了反射?
asp.net MVC 、ORM、LOC、AOP几乎所有的裤架都会使用反射

C#里面@符号和$符号的作用

(1)@字符的作用
C#字符串中不能使用没有经过转义的反斜杠字符 " \ “,而需要两个反斜杠字符来表示它:
string filePath=” C:\ProCSharp\First.cs “;
但这种方式容易令人产生疑惑,因此C#提供了替代方式。即可以在字符串字面量的前面加上字符@,在这个字符后的所有字符都看成其原来的含义。
string filePath=@” C:\ProCSharp\First.cs "
(2) 字 符 的 作 用 对 字 符 串 加 上 字符的作用 对字符串加上 前缀,就允许把花括号放在包含一个变量甚或代码表达式的字符串中。变量或代码表达式的结果放在字符串中花括号所在的位置:

#C#里面Debug和Release模式区别
release和debug是不同的运行方式:
debug会增加调试代码,方便调试。调试完后,用release版本发布,没有调试代码,减小程序体积,
加快执行速度!

C#里面字典和Hashtable

Dictionary
Dictionary:
必须包含名空间System.Collection.Generic
Dictionary里面的每一个元素都是一个键值对(由二个元素组成:键和值)
键必须是唯一的,而值不需要唯一的
键和值都可以是任何类型(比如:string, int, 自定义类型,等等)
通过一个键读取一个值的时间是接近O(1)
键值对之间的偏序可以不定义

使用方法:

//定义
Dictionary<string, string> openWith = new Dictionary<string, string>();

//添加元素
openWith.Add("txt", "notepad.exe");
openWith.Add("bmp", "paint.exe");
openWith.Add("dib", "paint.exe");
openWith.Add("rtf", "wordpad.exe");

//取值
Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]);

//更改值
 openWith["rtf"] = "winword.exe";
 Console.WriteLine("For key = \"rtf\", value = {0}.", openWith["rtf"]);

 //遍历key
  foreach (string key in openWith.Keys)
  {
        Console.WriteLine("Key = {0}", key);   //获得key(键的值)
        
   }

   //遍历value ,方法一
   foreach (string value in openWith.Values)   
   {
       Console.WriteLine("value = {0}", value);  
    }
     //方法二
    foreach (string key in openWith.Keys)
    {
        Console.WriteLine("Values={0}",openWith[key]);  //获得key(键)的values(值)
    }

    //删除元素
    openWith.Remove("doc");
    if (!openWith.ContainsKey("doc"))
    {
         Console.WriteLine("Key \"doc\" is not found.");
     }

     //判断键存在
    if (openWith.ContainsKey("bmp")) // True 
    {
          Console.WriteLine("An element with Key = \"bmp\" exists.");
     }

常用属性
名称 说明
Comparer 获取用于确定字典中的键是否相等的 IEqualityComparer。
Count 获取包含在 Dictionary<TKey, TValue> 中的键/值对的数目。
Item 获取或设置与指定的键相关联的值。
Keys 获取包含 Dictionary<TKey, TValue> 中的键的集合。
Values 获取包含 Dictionary<TKey, TValue> 中的值的集合。

常用方法
名称 说明
Add 将指定的键和值添加到字典中。
Clear 从 Dictionary<TKey, TValue> 中移除所有的键和值。
ContainsKey 确定 Dictionary<TKey, TValue> 是否包含指定的键。
ContainsValue 确定 Dictionary<TKey, TValue> 是否包含特定值。
Equals(Object) 确定指定的 Object 是否等于当前的 Object。 (继承自 Object。)
GetType 获取当前实例的 Type。 (继承自 Object。)
Remove 从 Dictionary<TKey, TValue> 中移除所指定的键的值。
ToString 返回表示当前对象的字符串。 (继承自 Object。)
TryGetValue 获取与指定的键相关联的值。

Hashtable

  1. 哈希表(HashTable)简述
    在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似
    keyvalue的键值对,其中key通常可用来快速查找,同时key是区分大小写;value用于存储对应于key的值。
    Hashtable中keyvalue键值对均为object类型,所以Hashtable可以支持任何类型的keyvalue键值对.

  2. 什么情况下使用哈希表
    (1)某些数据会被高频率查询
    (2)数据量大
    (3)查询字段包含字符串类型
    (4)数据类型不唯一

using System;
using System.Collections; //file使用Hashtable时,必须引入这个命名空间
class Program
{
public static void Main()
{
Hashtable ht = new Hashtable(); //创建一个Hashtable实例
ht.Add(“北京”, “帝都”); //添加keyvalue键值对
ht.Add(“上海”, “魔都”);
ht.Add(“广州”, “省会”);
ht.Add(“深圳”, “特区”);

 string capital = (string)ht["北京"];
 Console.WriteLine(capital)  //打印key="北京"的values值 结果:帝都
 Console.WriteLine(ht.Contains("上海")); //判断哈希表是否包含特定键,其返回值为true或false
 ht.Remove("深圳"); //移除一个keyvalue键值对

 //遍历values
foreach (string value in ht.Values)
{
        Console.WriteLine(value);
}

 ht.Clear(); //移除所有元素

}
}

Dictionary和Hashtable区别
HashTable和Dictionary的区别:
(1).HashTable不支持泛型,而Dictionary支持泛型。
(2). Hashtable 的元素属于 Object 类型,所以在存储或检索值类型时通常发生装箱和拆箱的操作,所以你可能
需要进行一些类型转换的操作,而且对于int,float这些值类型还需要进行装箱等操作,非常耗时。
(3).单线程程序中推荐使用 Dictionary, 有泛型优势, 且读取速度较快, 容量利用更充分。多线程程序中推荐使用
Hashtable, 默认的 Hashtable 允许单线程写入, 多线程读取, 对 Hashtable 进一步调用 Synchronized() 方法可以
获得完全线程安全的类型. 而 Dictionary 非线程安全, 必须人为使用 lock 语句进行保护, 效率大减。
(4)在通过代码测试的时候发现key是整数型Dictionary的效率比Hashtable快,如果key是字符串型,Dictionary
的效率没有Hashtable快。

#C#里面set和get访问器
属性的访问器包含与获取(读取或计算)或设置(写)属性有关的可执行语句。访问器声明可以包含 get 访问器或 set 访问器,
或者两者均包含。

get {}:get 访问器体与方法体相似。它必须返回属性类型的值。执行 get 访问器相当于读取字段的值。
private string name; // the name field
public string Name // the Name property
{
get
{
return name;
}
}

set {}:set 访问器与返回 void 的方法类似。它使用称为 value 的隐式参数,此参数的类型是属性的类型。
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}

只带有 get 访问器的属性称为只读属性。无法对只读属性赋值。
只带有 set 访问器的属性称为只写属性。只写属性除作为赋值的目标外,无法对其进行引用。
同时带有 get 和 set 访问器的属性为读写属性。
在属性声明中,get 和 set 访问器都必须在属性体的内部声明。

注意:使用get访问器更改对象的状态是一种错误的编程方式,尽量不要在get访问器中更改对象的状态。
eg:
public int Number
{
get
{
return number++; // Don’t do this
}
}

使用属性方式访问属性:
使用这种方式需要注意,同一属性的get和set方法不能够分开定义。及name属性的set和get方法都要放在
public string Name的属性定义中,若有两个public string Name编译会报错。编译器会认为Student类定
义了两个同名的属性,一个只读一个只写。

eg:
class Student
{
private string name;
private int number;
public string Name
{
set
{
name = value;
}
get
{
return name;
}
}
public int Number
{
set
{
number = value;
}
get
{
return number;
}
}
}

set和get访问器的好处:1、读取设置分开,这样代码便于维护,当访问器中的某个字段需要添加新的判断条件时候,
只需要在访问器中添加判断语句或者做条件修改,而无需给程序中所有该字段添加判断和条件语句。

C#里面泛型

List objlist=new List() {}; object类型做数据转换时候有拆装箱操作,有性能损耗,建议少用。

泛型约束:定义泛型时,可以对泛型类或泛型接口,方法能够接收的类型参数的种类加以限制。在编译阶段,
如果使用不符合要求的类作为类型参数,则会产生编译错误。

六种约束的格式说明
where T:struct
class Stack where TElement :struct
限制类型参数必须是值类型,并且不可以是可空值类型(例如int?,char?,double?,bool?等)

where T: class
class Stack where TElement :class
限制类型参数必须是引用类型

where T:基类名
class Stack where TElement :BaseClass
限制类型参数必须是继承自指定的基类,或是基类本身

where T:接口名
class Stack where TElement :IInterface
限制类型参数必须是实现指定接口,或是指定接口

where T:new()
class Stack where TElement :new()
限制类型参数必须具有无参构造函数
对new()解释说到是where字句的构造函数约束,带有new()约束的任何类型都必须有可访问的无参构造函数,
正常来说C#创建的类默认都有一个无参的构造函数,即使你没有写,但是如果你写了一个有参数的构造函数后,
那么就没有默认无参的那个了,就需要自己手动写一个。
其实说的很明白,就是where字句后面有new()约束的话,该类中必须有公有的无参的构造函数。
当出现这种情况时候:
public static void show(T t)where T:new() //这个约束表示T类型只接受带一个无参构造函数的类型对象

#C#里面强类型和弱类型
强类型和弱类型的变量都有两个属性:类型和值。

强类型的变量类型是不能改变的,弱类型的变量类型是随需改变的,这是强弱的真正含义。

C#里面强类型和弱类型

强类型和弱类型的变量都有两个属性:类型和值。

强类型的变量类型是不能改变的,弱类型的变量类型是随需改变的,这是强弱的真正含义。

C#里面线程

在C#中,线程是使用Thread类处理的,该类在System.Threading命名空间中。使用Thread类创建线程时,
只需要提供线程入口,线程入口告诉程序让这个线程做什么。通过实例化一个Thread类的对象就可以创建一
个线程。创建新的Thread对象时,将创建新的托管线程。Thread类接收一个ThreadStart委托或
ParameterizedThreadStart委托的构造函数,该委托包装了调用Start方法时由新线程调用的方法,示例代码如下:

Thread thread=new Thread(new ThreadStart(method));//创建线程
thread.Start(); //启动线程

ParameterizedThreadStart委托一个对象作为参数,利用这个参数可以很方便地向线程传递参数,示例代码如下:

Thread thread=new Thread(new ParameterizedThreadStart(method));//创建线程
thread.Start(3); //启动线程

C#里面虚方法与隐藏方法

虚方法:
将一个基类函数声明为virtual,就可以在任何派生类中重写该函数。
class MyBaseClass{
public virtual string VirtualMethod(){
return “Method is called in base class.”
}
}

在派生类中进行重写该函数时,需要使用override关键字显示声明
class MyDerivedClass : MyBaseClass{
public override string VirtualMethod(){
return “Method is called in derived class.”
}
}

隐藏方法
如果签名相同的方法在基类和派生类中都进行了声明,但是该方法并没有分别声明virtual和override,这是派生类就会隐藏基类方法(可以使用new关键字进行声明)
一个方法的签名即为一个方法的定义,例如返回值、参数、方法名等。

隐藏和重写的区别:
隐藏:只是将父类中的方法给隐藏了,实际这个方法还存在。
重写:将原先父类中的方法完全重写了,原先的方法是不存的了。

//隐藏方法:如果使用子类声明的对象,则调用隐藏方法会调用子类的;如果使用父类声明的对象,则会调用父类中的隐藏方法。
//父类:Enemy
//子类:Boss
//Move()是一个隐藏方法

class Enemy{
public string Move(){
return “This is Move from Enemy!”;
}
}

class Boss : Enemy{
public new string Move(){
return “This is Move from Boss!”;
}
}

Boss boss = new Boss();
boss.Move(); //This is Move from Boss!

Enemy boss = new Boss();
boss.Move(); //This is Move from Enemy!

//构造一样,但是声明不一样,调用的隐藏方法也是不一样的。
//一般不去使用隐藏方法,因为很容易引起方法调用的混乱。

C#里面异常处理

常见的异常类型:
System.IO.IOException 处理 I/O 错误。
System.IndexOutOfRangeException 处理当方法指向超出范围的数组索引时生成的错误。
System.ArrayTypeMismatchException 处理当数组类型不匹配时生成的错误。
System.NullReferenceException 处理当依从一个空对象时生成的错误。
System.DivideByZeroException 处理当除以零时生成的错误。
System.InvalidCastException 处理在类型转换期间生成的错误。
System.OutOfMemoryException 处理空闲内存不足生成的错误。
System.StackOverflowException 处理栈溢出生成的错误。

C#里面值类型和引用类型

概念:值类型直接存储其值,而引用类型存储对其值的引用。

引用类型:基类为Objcet
值类型:均隐式派生自System.ValueType:

值类型:
byte,short,int,long,float,double,decimal,char,bool 和 struct 统称为值类型。
引用类型:
string 和 class统称为引用类型。
· 值类型变量声明后,不管是否已经赋值,编译器为其分配内存。
· 引用类型当声明一个类时,只在栈中分配一小片内存用于容纳一个地址,而此时并没有为其分配堆上的内存空间。
当使用 new 创建一个类的实例时,分配堆上的空间,并把堆上空间的地址保存到栈上分配的小片空间中。
· 值类型的实例通常是在线程栈上分配的(静态分配),但是在某些情形下可以存储在堆中。
· 引用类型的对象总是在进程堆中分配(动态分配)。

C#里面字段属性和方法的区别

变量:变量亦称字段

字段:“字段"是直接在"类"或"结构"中声明的任何类型的变量。字段是其包含类型的"成员”.(简单的说,字段就是直接出现在类
或结构中的变量)

属性:属性是面向对象编程的基本概念,提供了对私有字段的访问封装,在C#中以get和set访问器方法实现对可读可写属性的操作,
提供了安全和灵活的数据访问封装.(这里与上面字段介绍 相呼应)
属性是这样的成员:它提供灵活的机制来读取,编写或计算某个私有字段的值.可以像使用公共数据成员一样使用属性,但实际上它们
是称作"访问器"的特殊方法.这使得可以轻松访问数据,此外还有助于提高方法的安全性和灵活性.

方法:完成特定功能,构造函数其实也是一种方法,只不过比较特殊

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值