c#
行走剑客
因为热爱,所以执着
展开
-
C# 运算符重载 --- 示例
下面是 Vector 的定义, 包含只读属性, 构造函数和重写的 ToString() 方法, 最后是运算重载符struct Vector{ public Vector(double x, double y, double z) { X = x; Y = y; Z = z; } public Vector(Vector v) { X = v.X; Y = v.Y; .原创 2020-05-22 13:22:41 · 654 阅读 · 0 评论 -
C# 运算符重载 --- 运算符的工作方式
想要了解运算符是如何重载的 , 就要考虑再编译器遇到运算符时会发生什么情况,这个很有用。用加法运算符作为例子,假设编译器处理下面的代码:int myInt = 3;uint myUint = 2;double myDouble = 4.0;long myLong = myInt + myUint;double myOtherDouble = myDouble + myInt;考虑当代码遇到下面这行代码会发生什么情况:long myLong = myInt + myUint;编原创 2020-05-21 12:01:25 · 262 阅读 · 0 评论 -
C# 运算符重载篇
运算符重载的关键是在对象上不能总是只调用方法或属性, 有时还需要做一些其他工作,例如对数值进行相加,相乘或逻辑(比较对象)等。假定已经定义了一个表示数学矩阵类。 在数学领域中,矩阵可以相加和相乘, 就像数字一样。所以可以编写下面的代码:Matrix a,b,c;Matrix d = c * ( a + b );通过运算符重载,就可以告诉编译器 " + " 和 " *" 对Matrix对象执行什么操作, 以便编写类似于上面的代码。 如果用不支持运算符重载的语言编写代码,就必须定义...原创 2020-05-21 11:31:37 · 380 阅读 · 0 评论 -
C# 比较对象的相等性(长文慎入)
理解对象相等的机制对逻辑表达式的编程非常重要, 另外对实现运算符重载和类型强制转换也非常重要。对象相等的机制有所不同,这取决于比较的是引用类型(类的实例),还是值类型(基本数据类型, 结构 或 枚举的实例)。本章会单独介绍引用类型的相等性和值类型的相等性。比较引用类型的相等性System.Object 定义了3个不同的方法来比较对象的相等性 : ReferenceEquals() 和两个版本的 Equals(). 再加上比较运算符 == ,实际上有4种比较相等性的方法。 这些.原创 2020-05-20 11:04:59 · 564 阅读 · 0 评论 -
C# 装箱和拆箱
装箱(boxing)装箱用于描述把一个值类型转换为引用类型。运行库会为堆上的对象创建一个临时的引用类型 "箱子"int myAge = 30;object myObj = myAge; // boxing拆箱(unboxing)拆箱用于描述相反的过程, 就是把装箱的值类型强制转换回值类型。 这里使用术语 "强制转换" ,因为转换是显示进行的。其语法类似于前面的装箱:int myAge = 30;object myObj = myAge; // boxingint ..原创 2020-05-19 10:47:59 · 132 阅读 · 0 评论 -
C# 隐式类型转换表
原创 2020-05-19 10:30:00 · 181 阅读 · 0 评论 -
C# 空值传播运算符
这是 C#6 的一个非常优秀的新功能空值传播运算符。在程序开发时,会遇到大量的代码都需要验证空值条件。如果不做处理,遇到空值会抛出错误信息, 所以要养成一个良好的习惯,检查空值。当然,在实际开发中,总是很容易漏掉这样的检查。 我们先看一个例子:public void ShowPerson(Person person){ if(person == null) return; string name = person.Name;}这段代码检查了 person对象是否为空,..原创 2020-05-19 10:16:22 · 1854 阅读 · 1 评论 -
C# 两个问号 ?? 空合并运算符
空合并运算符(??) 可以在处理可空类型和引用类型时表示 null 值的可能性。这个运算符放在两个操作数之间, 第一个操作数必须是一个可空类型或引用类型, 第二个操作数必须与第一个操作数的类型相同,或者可以隐式地转换为第一个操作数的类型。可空运算符的计算如下:如果第一个操作数不是 null, 整个表达式就等于第一个操作数的值。 如果第一个操作数是 null, 整个表达式就等于 第二个操作数的值。举个例子:// 可空的值类型string? name = null;in...原创 2020-05-19 09:38:53 · 195 阅读 · 0 评论 -
C# sizeof 和 typeof 运算符
sizeof 运算符使用 sizeof 运算符可以确定栈中值类型需要的长度(单位是字节):Console.WriteLine( sizeof(int) );// 输出结果4 因为int类型有4个字节。所以返回4;typeof 运算符typeof 运算符返回一个表示特定类型的 System.Type 对象。例如, typeof(string) 返回表示 System.String 类型的 Type 对象。 在使用反射技术动态地查找对象的相关信息, 这个运算符很有用。..原创 2020-05-19 09:09:09 · 512 阅读 · 0 评论 -
C# 条件运算符(三元运算符)
条件运算符 (?:) 也称为三元运算符,是 if...else 结构的简化形式。它首先判断一个条件,如果条件为真,就返回一个值,如果条件为假,则返回另一个值。condition ? true_value : false_value;condition 是布尔表达式, ture_value 是 condition 为真时返回的值, false_value 是 condition为假是返回的值。恰当的使用三元运算符,可以使程序非常简洁。举个例子, 检查用户年龄是否满18周岁, ...原创 2020-05-15 11:03:39 · 2192 阅读 · 0 评论 -
C# 元组
数组合并了相同类型的对象,而元组合并了不同类型的对象。元组起源于函数编程语言(如F#),在这些语言中频繁使用元组。在 .NET Framework 中,元组可用于所有的 .NET语言。.NET Framework 定义了 8个泛型 Tuple 类和一个静态的 Tuple类, 他们用作元组的工厂。 不同的泛型 Tuple 类支持不同数量的元素。 例如 Tuple<T1> 包含一个元素, Tuple<T1,T2>包含两个元素,以此类推。public static Tup.原创 2020-05-15 10:40:25 · 2287 阅读 · 0 评论 -
C# Array类---排序(长文慎入)
Array类使用 Quicksort 算法对数组中的元素进行排序。 Sort() 方法需要数组中的元素实现 IComparable 接口。 因为简单类型 如 System.String 和 System.Int32 实现了 IComparable 接口, 所以可以对包含这些类型的元素排序。我们看个栗子:string[] names = { "Zhang San", "Li Si", "Wang Er", "Ma Zi"};Array.Sort( names )原创 2020-05-14 13:17:17 · 760 阅读 · 0 评论 -
C# Array类---复制数组
因为数组是引用类型, 所以将一个数组变量赋予另一个数组变量,就会得到两个引用同一数组的变量。而复制数组,会使数组实现ICloneable 接口。 这个接口定义的 Clone() 方法会创建数组的浅表副本。如果数组的元素是值类型, 下面的例子中就会复制所有值:int[] intArray1 = {1,2};int[] intArray2 = (int[]) intArray1.Clone();如果数组包含引用类型, 则不复制元素,而只复制引用。下面看一个数组的元素是引用类型的案例:.原创 2020-05-14 10:47:11 · 341 阅读 · 0 评论 -
C# Array类---创建数组
Array 类是一个抽象类,所以不能实例化它。除了使用C# 语法 "[ ]" 创建数组之外,还可以使用静态方法 CreateInstance() 创建数组。举个例子:Array intArray1 = Array.CreateInstance( typeof(int), 5 );for(int i = 0; i < 5; i++){ intArray1.SetValue( i+1 , i );}for(int i = 0; i < 5; i++){ ...原创 2020-05-14 10:33:39 · 1494 阅读 · 0 评论 -
C# Array类
用方括号声明数组是c#中使用 Array类的表示法。 在后台使用c#语法, 会创建一个派生自抽象基类 Array的新类。 这样,就可以使用Array类为每个c#数组定义的方法和属性了。 例如前两节关于数组文章中,就用到了 Length 属性, 或者使用 foreach 语句迭代数组。 其实这是使用了 Array类中的 GetEnumerator() 方法。Array 类实现的其他属性有 LongLength 和 Rank。 如果数组包含的元素个数超出了整数的取值范围,就可以使用 LongLength属性原创 2020-05-14 10:18:32 · 373 阅读 · 0 评论 -
C# 多维数组
一般数组(也称为一维数组) 用一个整数来索引。 多维数组用两个或多个整数来索引。上图是一个 二维数组的数学表示法, 该数组有 3行 3列。 第一行的值是 1,2,3 第二行是 4,5,6 第三行是 7,8,9在C#中声明这个二维数组,需要在方括号中加上一个逗号。数组在初始化时应指定每一维的大小(也称为阶)。 接着,就可以使用两个整数作为索引器来访问数组中的元素, 下面举个栗子:int[,] twodim = new int[3,3];twodim[0,0] = 1;twodim[.原创 2020-05-13 11:57:44 · 704 阅读 · 0 评论 -
C# 数组
数组是做什么的?如果需要使用同一个类型的多个对象,就可以使用数组。数组是一种数据结构,它可以包含同一类型的多个元素如何声明数组?在声明数组时,应先定义数组中元素的类型, 其后是一对空方括号和一个变量名。int[] intArray;数组如何初始化?声明数组后,就必须为数组分配内存, 用以保存数组的所有元素。 数组是引用类型,所以必须给它分配堆上的内存。 为此,应使用 new 运算符, 指定数组中元素的类型和数量来初始化数组的变量。int[] intArray..原创 2020-05-13 11:19:52 · 146 阅读 · 0 评论 -
C# 泛型方法
除了定义泛型类之外,还可以定义泛型方法。 在泛型方法中,泛型类型用方法声明来定义。泛型方法可以在非泛型类中定义。// Swap<T>() 方法把 T 定义为泛型类型。void Swap<T> (ref T x, ref T y){ T temp; temp = x; x = y; y = temp;}测试调用:int i = 4;int j = 5;Console.WriteLine("i = " + i);Cons.原创 2020-05-13 10:32:42 · 211 阅读 · 0 评论 -
C# 泛型接口的抗变
如果泛型类型用 in 关键字标注, 泛型接口就是抗变的。这样就只能把T用作方法的输入参数语法如下:public interface IDisplay<in T>{ void Show (T item);}ShapeDisplay 类实现 IDisplay<Shape> , 并使用 Shape 对象作为输入参数public class ShapeDisplay : IDisplay<Shape>{ public void Sho.原创 2020-05-11 11:40:31 · 115 阅读 · 0 评论 -
C# 泛型接口的协变
如果泛型类型用 out 关键字标注, 泛型接口就是协变的。这也意味着返回类型只能是T。public interface IIndex<out T>{ T this[int index] {get;} int Count {get;}}上面例子中 IIndex 与类型 T是协变的, 并从一个只读索引器中返回这个类型。IIndex<T> 接口用 RectangleCollection 类来实现。 RectangleCollection 类为泛型类型..原创 2020-05-11 11:23:57 · 232 阅读 · 0 评论 -
C# 泛型---协变和抗变
在.net4 之前,泛型接口是不变的。.net4 通过协变和抗变为泛型接口和泛型委托添加了一个重要的扩展。协变和抗变指对参数和返回值的类型进行转换。参数类型是协变的例如,可以给一个需要 Shape 参数的方法传送 Rectangle 参数吗? 下面用示例说明这些扩展的优点。在.net中,参数类型是协变的。 假定有 Shape 和 Rectangle 类, Rectangle派生自 Shape基类。 声明 Display() 方法是为了接受 Shape 类型的对象作为其参数:..原创 2020-05-11 11:03:09 · 248 阅读 · 0 评论 -
C# 泛型---静态成员
泛型类的静态成员需要特别关注。 泛型类的静态成员只能在类的一个实例中共享, 下面看一个例子:public class StaticDemo<T>{ public static int x; // 静态字段}由于同时对一个 string 类型和一个 int 类型使用了 StaticDemo<T> 类, 因此存在两组静态字段:StaticDemo<string>.x = 4;StaticDemo<int>.x = 5;Conso.原创 2020-05-11 10:10:12 · 965 阅读 · 0 评论 -
C# 泛型---继承
泛型类型可以实现泛型接口,也可以派生自一个类。 泛型类可以派生自泛型基类泛型类型继承写法:public class Base<T>{}public class Derived<T> : Base<T>{}指定基类的类型写法:public class Base<T>{}public class Derived<T> : Base<string>{}写一个从 Query 中派生 ..原创 2020-05-11 10:04:42 · 2237 阅读 · 0 评论 -
C# 泛型约束
如果知道泛型约束或了解过泛型约束的,看上面的图片就够了, 如果大家还完全不理解泛型约束的概念, 继续往下看如果泛型类需要调用泛型类型中的方法,就必须添加约束。举个例子: public class AnimalManager<T> { public readonly List<T> animalList = new List<T>(); public void AddAnimal(T obj) ...原创 2020-05-09 10:55:20 · 429 阅读 · 0 评论 -
C# 泛型之 default 关键字
泛型类型不能直接赋值为null, 这时候要用 default 关键字 :public T GetData(){ T data = default(T); // 这里演示了如何使用 default 关键字 // 做点什么 return data;}注意: default 关键字根据上下文可以有多种含义。 switch 语句中使用 default 定义默认情况。 在泛型中,取决于泛型类型是引用类型还是值类型, 泛型 default 将泛型类型初始化为 nul.原创 2020-05-09 09:21:11 · 623 阅读 · 0 评论 -
C# 泛型---创建泛型类(例子)
每个处理对象类型的类都可以有泛型实现方式。 另外如果类使用了层次结构,泛型就非常有助于消除类型强制转换操作public class LinkedListNode<T>{ public LinkedListNode(T value) { Value = value; } public T Value {get; pri...原创 2020-05-08 13:58:37 · 817 阅读 · 0 评论 -
C# 泛型---命名约定
泛型时 c# 和 .net 的一个重要概念。泛型不仅是 c# 编程语言的一部分, 而且与程序集中的 IL(Intermediate Language) 代码紧密地集成。 有了泛型, 就可以创建独立于被包含类型的类放方法。 我们不必给不同的类型编写...原创 2020-05-08 11:13:10 · 448 阅读 · 0 评论 -
C# using语句
using 语句的后面是一对圆括号, 其中是引用变量的声明和实例化, 该语句使变量的作用域限定在随后的语句块中。 另外在变量超出作用域时, 即使出现异常,也会自动调用 Dispose() 方法。using(WWW www = new WWW(url)){ // 做点什么}using 关键字在 c# 中有的用法:using 声明用于导入名称空间。 using 语句处理实现...原创 2020-05-07 10:17:39 · 318 阅读 · 0 评论 -
C# 内存管理篇---IDisposable接口
//todo原创 2020-05-07 09:18:27 · 493 阅读 · 0 评论 -
C# 内存管理篇---析构函数或终结器
// todo原创 2020-05-07 09:16:55 · 438 阅读 · 0 评论 -
C# 内存管理篇---处理非托管的资源
既然讲到了非拖管资源, 那就要先了解下什么是非托管资源。 例如我们经常使用的 文件句柄,网络连接,数据库连接等, 这些都是非托管资源。垃圾回收器不知道如何释放非托管资源,托管类在封装对非托管资源的直接或间接引用时,需要制定专门的规则,确保非托管的资源在回收类的一个实例时释放。在定义一个类时,可以使用两种机制来自动释放非托管的资源。这些机制常常放在一起实现,因为每种机制都为问题提供了略...原创 2020-05-07 09:18:50 · 536 阅读 · 1 评论 -
C# 内存管理篇---强引用和弱引用
垃圾回收器不能回收仍在引用的对象的内存,这是一个强引用它可以回收不在根表中直接或间接引用的托管内存。 然而,有时可能会忘记释放引用。注意:如果对象互相引用,但没有在根表中引用, 例如, 对象A引用B, B引用C, C引用A, 则GC可以销毁所有这些对象。在应用程序代码内实例化一个类或结构时, 只要有代码引用它, 就会形成强引用。 例如,如果有一个类 MyClass, 并创建了一个变...原创 2020-05-06 10:58:50 · 673 阅读 · 0 评论 -
C# 内存管理篇---垃圾回收
在垃圾回收器运行时,它会从堆中删除不再引用的所有对象。托管堆的工作方式非常类似于栈,对象会在内存中一个挨一个地放置, 这样就很容易使用指向下一个空闲存储单元的堆指针来确定下一个对象的位置。垃圾回收器在引用的根表中找到所有引用的对象,接着在引用的对象树中查找。在完成删除操作后,堆会立即把对象分散开来,与已经释放的内存混合在一起。删除后空闲空间是分散的,如果这时候给新对象分配内存就...原创 2020-05-06 10:25:30 · 269 阅读 · 0 评论 -
C# 内存管理篇---引用数据类型
虽然栈有非常高的性能,但它还没有灵活到可以用于所有的变量。 变量的生存期必须嵌套,在许多情况下,这种要求都过于苛刻。通常我们希望使用一个方法分配内存, 来存储一些数据, 并在方法退出后的很长一段时间内数据仍然可用。 只要是用 new 运算符来请求分配存储空间,就存在这种可能性, 例如,对于所有的引用类型。 此时就要用到托管堆。托管堆简称堆是处理器的可用内存中的另一个内存区域。要了解堆的工作...原创 2020-05-05 11:16:14 · 219 阅读 · 0 评论 -
C# 内存管理篇---值数据类型
Windows 使用一个虚拟寻址系统, 该系统把程序可用的内存地址映射到硬件内存中的实际地址上,这些任务完全由Windows在后台管理。 其实际结果是32位处理器上的每个进程都可以使用4GB的内存, 无论计算机上实际有多少物理内存(64位处理器上,这个数字会更大)。在这个4GB的内存实际上包含了程序的所有部分,包括可执行代码、代码加载的所有DLL, 以及程序运行时使用的所有变量的内容。 这个4GB...原创 2020-05-05 10:25:35 · 174 阅读 · 0 评论 -
C# 内存管理篇
C#编程的一个优点是程序员不需要担心具体的内存管理,垃圾回收器会自动处理所有的内存清理工作。 用户可以得到像C++语言那样的效率, 而不需要考虑像在C++中那样内存管理工作的复杂性。 虽然不用手动管理内存,但是仍需要理解后台发生的事情。 理解程序在后台如何管理内存有助于提高应用程序的速度和性能。 后面在内存管理篇中将会介绍给变量分配内存时在计算机的内存中发生的情况。注意: 本章节不详细介绍许多...原创 2020-05-05 09:46:44 · 291 阅读 · 0 评论 -
C# is和as运算符
两个与继承有关的重要运算符 is 和 asIBankAccount venusAccount = new SaverAccount();如上,可以把具体类型的对象直接分配给基类或接口。 如果一个方法接受一个对象类型, 现在希望访问 IBankAccount 成员,该怎么办?该对象类型没有 IBankAccount 接口的成员。 此时可以进行类型转换。 把对象(也可以使用任何接口中任意...原创 2020-04-29 15:50:55 · 208 阅读 · 0 评论 -
C# 派生的接口
接口可以继承接口,其方式与类的继承方式相同。 下面通过定义一个新的 ITransferBankAccount 接口来说明这个概念,该接口的功能与 IBankAccount 相同, 只是又定义了一个方法,把资金直接转到另一个账户上:public interface ITransferBankAccount : IBankAccount{ bool TransferTo(IBankAc...原创 2020-04-29 15:24:14 · 327 阅读 · 0 评论 -
C# 定义和实现接口(小例子)
下面开发一个遵循接口继承的小例子来说明如何定义和使用。假设这个例子建立在银行账户的基础上。 假定编写代码,表示银行账户的所有类都实现接口 IBankAccount. 该接口包含一个用于存取款的方法和一个返回余额的属性。// 通常接口名称以字母I开头public interface IBankAccount{ void PayIn (decimal amount); ...原创 2020-04-29 14:59:32 · 2461 阅读 · 0 评论 -
C# 接口
如果一个类派生自一个接口,声明的这个类就会实现某些函数。public interface IFly{ void Fly();}声明接口在语法上与声明抽象类完全相同,但不允许提供接口中任何成员的实现方式。一般情况下,接口只能包含方法、属性、索引器和事件的声明。比较接口和抽象类:抽象类可以有实现代码或没有实现代码的抽象成员。 然而,接口不能有任何实现代码。 它是纯粹抽象...原创 2020-04-29 14:06:04 · 285 阅读 · 0 评论