wordpress远程调用cdn,seo外链建设的方法有,如何用js做网站,做电影网站怎么降低内存文章目录 引用类型class匿名类 记录引用相等和值相等record声明 接口delegate 委托合并委托/多路广播委托 引用类型
引用类型的变量存储对其数据#xff08;对象#xff09;的引用#xff0c;而值类型的变量直接包含其数据。 对于引用类型#xff0c;两种变量可引用同一对… 文章目录 引用类型class匿名类 记录引用相等和值相等record声明 接口delegate 委托合并委托/多路广播委托 引用类型
引用类型的变量存储对其数据对象的引用而值类型的变量直接包含其数据。 对于引用类型两种变量可引用同一对象因此对一个变量执行的操作会影响另一个变量所引用的对象。 对于值类型每个变量都具有其自己的数据副本对一个变量执行的操作不会影响另一个变量in、ref 和 out 参数变量除外。
在前文中我们常常说引用类型比值类型要好一方面引用类型的对象类似于指针不同的变量会指向同一个对象。而值类型则是将定义的值克隆一个副本赋值给新的变量。从性能方面引用类型就更好并且从内存方面考虑引用类型存放在CLR的虚拟机堆中而值类型存放在栈中在堆中可以对数据直接处理而在栈中则需要将其前面的内存出栈从内存方面使用引用类型也更好。而具体的关于引用和值类型在内存中的关系将在未来GC的章节中描述。 class
类应该是最熟悉的一种引用类型了
class ClassA { } --直接定义类
class DerivedClass : BaseClass { } --继承单个类
class ImplClass : IFace1, IFace2 { } -- 实现两个接口
class ImplDerivedClass : BaseClass, IFace1 { } --继承一个类实现一个接口在C#中我们只能继承一个类但是可以继承多个接口。看到本文我默认你学过面向对象了
匿名类
匿名类型提供了一种方便的方法可用来将一组只读属性封装到单个对象中而无需首先显式定义一个类型。 类型名由编译器生成并且不能在源代码级使用。 每个属性的类型由编译器推断。
var v new { Amount 108, Message Hello };
// Rest the mouse pointer over v.Amount and v.Message in the following
// statement to verify that their inferred types are int and string.
Console.WriteLine(v.Amount v.Message); //108Hello使用匿名类我们定义新的对象的时候可以不必定义一个类这是为了方便我们进行一些对象的生成特别是当这个类是临时定义的只需要属性而不需要其他方法且有可能只会定义一次对象的时候。
匿名类型包含一个或多个公共只读属性。 包含其他种类的类成员如方法或事件为无效。 用来初始化属性的表达式不能为 null、匿名函数或指针类型。
在下例中我们用prod遍历了products集合并在每次创建一个新的匿名类其中属性为Color和Pirce
var productQuery from prod in productsselect new { prod.Color, prod.Price };foreach (var v in productQuery)
{Console.WriteLine(Color{0}, Price{1}, v.Color, v.Price);
}尽管我们并没有给匿名类中的属性创建变量名但是匿名类自动的将创建时的变量名作为了自己的变量名也就是创建时使用了prod.Color,prod.Price。它根据变量名为自己的属性也创建了相应的同名变量Color和Price。
还可以按另一种类型类、结构或另一个匿名类型的对象定义字段。 它通过使用保存此对象的变量来完成如以下示例中所示其中两个匿名类型是使用已实例化的用户定义类型创建的。 在这两种情况下匿名类型 shipment 和 shipmentWithBonus 中的 product 字段的类型均为 Product其中包含每个字段的默认值。 bonus 字段将是编译器创建的匿名类型。
var product new Product();
var bonus new { note You won! };
var shipment new { address Nowhere St., product };
var shipmentWithBonus new { address Somewhere St., product, bonus };在上述例子中我们可以看到匿名类本身的属性通常不需要定义类型而类型是由编译器自己决定的。而已有类型定义的变量则是其对应的类型例如product的类型是Product而bonus的类型则是匿名类。 由于匿名类的类型是不定的因此使用var关键字来定义这个匿名类。
如果想要修改匿名类中的属性可以使用with表达式来实现
var apple new { Item apples, Price 1.35 };
var onSale apple with { Price 0.79 };
var Banana apple with {}; // 使用with空值可以直接赋值注意with和record只能在C# 9以上的版本使用unity中暂时不可用 记录
记录是一个类或者结构体通过添加record修饰符声明
在下列情况下请考虑使用记录而不是类或结构
你想要定义依赖值相等性的数据模型。你想要定义对象不可变的类型。
值相等性的意思是两个作为相等比较的值只有当它们类型相等且属性的属性名相等且属性值相等才能视为相等。类似于内部的键值对需要完全相等。更具体的来说一般而言的相等性是引用相等性其相等比较在于如果两个类型引用同一个变量则认为它们相等。
不可变性就是在对象实例化后禁止更改该对象的任何属性或字段值。
引用相等和值相等
为了清楚引用相等和值相等请看下面几个例子
Product A new Product();
Product B new Product();
if (A B)
{Debug.Log(1); --输出不了
}第一个例子中AB是false的因为A和B作为引用类型它们的引用不相等
Product A new Product();
Product B A;
if (A B)
{Debug.Log(1); --输出1
}在第二个例子中B引用A而A引用的是new Product,所以二者引用相等。
值相等应当不必解释了就是平常意义上的相等
record声明
var phoneNumbers new string[2];
Person person1 new(Nancy, Davolio, phoneNumbers);
Person person2 new(Nancy, Davolio, phoneNumbers);
Console.WriteLine(person1 person2); // output: Trueperson1.PhoneNumbers[0] 555-1234;
Console.WriteLine(person1 person2); // output: TrueConsole.WriteLine(ReferenceEquals(person1, person2)); // output: False接口
接口是高度抽象的我们可以使用interface关键字定义一个接口在接口中我们只应当定义函数头其内部实现则完全由继承了接口的类来实现。
interface IEquatableT
{bool Equals(T obj);
}一个接口同样可以继承其他的接口当一个接口继承多个其他接口后这个接口被称为派生接口其他接口被称为基接口。一个继承了派生接口的类不仅需要实现派生接口中的所有方法也需要实现基接口中的所有方法
interface IBaseInterface
{void BaseMethod();
}
interface IEquatable : IBaseInterface
{bool Equals();
}
public class TestManager : IEquatable
{bool IEquatable.Equals(){throw new NotImplementedException();}void IBaseInterface.BaseMethod(){throw new NotImplementedException();}
}delegate 委托
委托的使用通常需要将方法作为参数传递给其他方法时。可以将委托视为调用一个事件时会触发的方法。相当于我们不必在事件或者函数内部定义一个回调参数而只需要把委托方法附加上去即可。
相较于接口委托更适合灵活的方法组合可以添加给多个事件。用我个人的理解来比喻点餐是一个事件假设这个饭店能APP点餐和服务员点餐而APP只能点套餐服务员可以一个菜一个菜给你加。现在我们分别要用委托和接口实现这个事件。委托像是有个服务员帮你点餐你只需要说想吃什么服务员就会帮你记下然后通知后厨。而接口像捆绑了一堆的套餐如果点了鸡腿套餐那一定会给你鸡腿米饭点了猪排套餐一定给你猪排米饭。而使用委托如果我们想要鸡腿米饭我们也可以让服务员给我们增加两个菜方法一个是鸡腿一个是米饭。但是如果我们想要的菜品多且和套餐重复的话那么接口可以更好的实现。但如果我们想要灵活地点菜例如我想要鸡腿米饭用接口实现了然后我又想要一个猪排如果用接口实现那接口会给我猪排米饭。如果我只想要猪排那就应该叫服务员来只点一个猪排。
委托可以和方法绑定当触发委托时自动触发绑定的方法
// Declare a delegate:
delegate void Del(int x);// Define a named method:
void DoWork(int k) { /* ... */ }// Instantiate the delegate using the method as a parameter:
Del d obj.DoWork;合并委托/多路广播委托
不同的委托之间可以合并
CustomDel hiDel, byeDel, multiDel, multiMinusHiDel;hiDel Hello;
byeDel Goodbye;
multiDel hiDel byeDel;
multiMinusHiDel multiDel - hiDel;委托的合并直接使用加法即可简单来说委托A委托B 合并委托C而合并委托C可以使用减法把委托A或者委托B减掉。加法就像服务员A和服务员B跟厨师说1号桌要XXX菜2号桌要XXX菜厨师肯定是哪桌先点餐哪桌先上菜。减法就是服务员B过来又说2号桌不要了你别做了那厨师只做服务员A委托的1号桌的菜就好了。
在调用多播委托时它会按顺序调用列表中的委托。 只能合并相同类型的委托。