当前位置: 首页 > news >正文

建网站的程序营销推广与策划

建网站的程序,营销推广与策划,wordpress 不能编辑,搜索引擎怎么收录网站ref 修饰符,指定参数由引用传递,可以由调用方法读取或写入。out 修饰符,指定参数由引用传递,必须由调用方法写入。in 修饰符,指定参数由引用传递,可以由调用方法读取,但不可以写入。in关键字 i…
  • ref 修饰符,指定参数由引用传递,可以由调用方法读取或写入。
  • out 修饰符,指定参数由引用传递,必须由调用方法写入。
  • in 修饰符,指定参数由引用传递,可以由调用方法读取,但不可以写入。

in关键字

in修饰符通过引用传递参数。 它让形参成为实参的别名,即对形参执行的任何操作都是对实参执行的。它类似于 ref 或 out 关键字,不同之处在于 in 参数无法通过调用的方法进行修改。

struct Product
{public int ProductId { get; set; }public string ProductName { get; set; }
}public static void Modify(in Product product)
{//product = new Product();          
// 错误 CS8331 无法分配到 变量 'in Product',因为它是只读变量//product.ProductName = "测试商品";  
// 错误 CS8332 不能分配到 变量 'in Product' 的成员,因为它是只读变量Console.WriteLine($"Id: {product.ProductId}, Name: {product.ProductName}"); 
// OK
}

引入 in ,out,ref参数的原因

我们知道,结构体实例的内存在栈(stack)上进行分配,所占用的内存随声明它的类型或方法一起回收,所以通常在内存分配上它是比引用类型占有优势的。

但是对于有些很大(比如有很多字段或属性)的结构体,将其作为方法参数,在紧凑的循环或关键代码路径中调用方法时,复制这些结构的成本就会很高。当所调用的方法不修改该参数的状态,使用新的修饰符 in ,out或ref声明参数以指定此参数可以按引用安全传递,可以避免(可能产生的)高昂的复制成本,从而提高代码运行的性能。

使用 in 参数需要注意的地方

struct MyNormalStruct
{public int Value { get; set; }public void UpdateValue(int value){Value = value;}
}class Program
{static void UpdateMyNormalStruct(MyNormalStruct myStruct){myStruct.UpdateValue(8);}static void Main(string[] args){MyNormalStruct myStruct = new MyNormalStruct();myStruct.UpdateValue(2);UpdateMyNormalStruct(myStruct);Console.WriteLine(myStruct.Value);}
}

正确输出结果是 2

修改UpdateMyNormalStruct方法的参数加上 in 修饰符

static void UpdateMyNormalStruct(in MyNormalStruct myStruct)
{myStruct.UpdateValue(8);
}

结果依然为 2 !

C# 无法知道当它调用一个结构体上的方法(或getter)时,是否也会修改它的值/状态。于是,它所做的就是创建所谓的“防御性副本”。当在结构体上运行方法(或getter)时,它会创建传入的结构体的副本,并在副本上运行方法。这意味着原始副本与传入时完全相同,调用者传入的值并没有被修改。

总结in关键字

  • 使用 in 参数,有助于明确表明此参数不可修改的意图。
  • 只读结构体(readonly struct的大小大于 IntPtr.Size 时,出于性能原因,应将其作为 in 参数传递。
  • 不要将一般(非只读)结构体作为 in 参数,因为结构体是可变的,反而有可能对性能产生负面影响,并且可能产生晦涩难懂的行为。

out关键字

1)带有out的形参,在函数定义时,return前必须给函数赋一个值。
2)调用函数时,带有out的参数不必赋一个初始值。
3)out形参传值是通过引用(by reference)

ref关键字

ref关键字用于改变参数传递,将by value修改为by reference传值,原来是by reference传递的,加上ref还是不加ref,效果是一样的。

ref和out的实质性区别

答案就在其修饰的实参和形参在地址空间的关系上。

1.对于ref,它修饰的形参会指向实参的地址,这样,在方法内对形参进行运算时,改变的就是实参地址上的值。(这就是为什么ref修饰的实参必须要赋初始值,因为这样,ref修饰的实参才能在内存中拥有自己的地址空间。在这里,大家可能对变量地址的分配有些疑问,那么我来补充一下:静态变量--全局变量 在定义时就会得到内存空间,而非静态变量--局部变量 直到赋给初始值时,才会得到内存空间)

2.对于out,它修饰的实参会指向形参的地址,这样,在方法内对形参进行运算时,改变的就是形参地址上的值。(这就是为什么out修饰的实参可以不赋初始值,因为out修饰的实参指向形参的地址空间)

3.对于普通的实参和形参来说,它们之间的关系发生在值上。简单来说,就是形参将实参的值拿来当作自己的值,而形参在方法内的运算就和实参没有什么关系了。

看以下这个例子:

    void Start(){Dog dog = null;CreateDog(dog);Debug.LogError(dog == null);}void CreateDog(Dog dog){dog = new Dog();}//------------------------分割线------------------------void Start(){Dog dog = null;CreateDog(ref dog);Debug.LogError(dog == null);}void CreateDog(ref Dog dog){dog = new Dog();}//------------------------分割线------------------------void Start(){Dog dog = null;CreateDog(out dog);Debug.LogError(dog == null);}void CreateDog(out Dog dog){dog = new Dog();}

上述打印结果依次为true和false和false。

逆变和协变

msdn 解释如下:

协变是指能够使用与原始指定的派生类型相比,派生程度更大的类型。

逆变则是指能够使用派生程度更小的类型。

解释的很正确,大致就是这样,不过不够直白。

直白的理解:

“协变”->”和谐的变”->”很自然的变化”->string->object :协变。

“逆变”->”逆常的变”->”不正常的变化”->object->string 逆变。

手动添加两个类:

    public abstract class Animal{}public class Dog : Animal{}

 Dog变成Animal 就是和谐的变化(协变),而如果Animal 变成Dog就是不正常的变化(逆变)

        Dog dog = new Dog();Animal animal = dog;List<Dog> dogList = new List<Dog>();List<Animal> animalList = dogList;

因为Dog继承自Animal,所以Animal animal = dog; dog会隐式的转变为Animal类型。

但是List<Dog> 不继承List<Animal> 所以

List<Animal> animalList = dogList无法编译通过。如果想要转换的话,应该使用下面的代码:

List<Animal> animalList = dogList.Select(d => (Animal)d).ToList();

正因如此,所以微软新增了两个关键字:out,in,下面是他们的msdn解释:

image

image

out 和in 关键字在接口和委托中使用,微软使用out 和 in 标记的接口和委托大致如下:

image

image

先看下第一个IEnumerable<T>

image

和刚开始说的一样,T 用out 标记,所以T代表了输出,也就是只能作为结果返回。

承接上文,以下写法便可以正常编译通过:

 IEnumerable<Animal> animalEnumerable = dogList;

上面演示的是协变,接下来要演示下逆变。

为了演示逆变,那么就要找个in标记的接口或者委托了,最简单的就是:

clip_image002

Action<Animal> actionAnimal = new Action<Animal>(a => {/*让动物叫*/ });Action<Dog> actionDog = actionAnimal;actionDog(dog);

很明显actionAnimal 是让动物叫,因为Dog是Animal,那么既然Animal 都能叫,Dog肯定也能叫。

in关键字:逆变,代表输入,代表着只能被使用,不能作为返回值,所以C#编译器可以根据in关键字推断这个泛型类型只能被使用,所以Action<Dog> actionDog = actionAnimal;可以通过编译器的检查。

再次演示out关键字:

添加两个类:

    public interface IMyList<out T>{T GetElement();}public class MyList<T> : IMyList<T>{public T GetElement(){return default(T);}}

因为out 关键字,所以下面的代码可以通过编译

IMyList<Dog> myDogs = new MyList<Dog>();
IMyList<Animal> myAnimals = myDogs;

修改上面两个类为:

    public interface IMyList<out T>{T GetElement();void ChangeT(T t);}public class MyList<T> : IMyList<T>{public T GetElement(){return default(T);}public void ChangeT(T t){}}

则无法通过编译,

 因为T被out修饰,所以T只能作为参数。

同样修改两个类如下,使用in关键字:

    public interface IMyList<in T>{T GetElement();void ChangeT(T t);}public class MyList<T> : IMyList<T>{public T GetElement(){return default(T);}public void ChangeT(T t){}}

 因为用in关键字标记,所以T只能被使用,不能作为返回值。

最后修改为:

    public interface IMyList<in T>{void ChangeT(T t);}public class MyList<T> : IMyList<T>{public void ChangeT(T t){}}

编译成功,因为in代表了逆变,所以

IMyList<Animal> myDogs = new MyList<Animal>();
IMyList<Dog> myAnimals = myDogs;

可以编译成功!

你还在哪些地方用到过in,out,ref关键字呢?欢迎评论区补充。

http://www.lbrq.cn/news/2377441.html

相关文章:

  • 深圳商城网站哪家做的好快速排名工具免费
  • 深圳政府采购中心官网四川整站优化关键词排名
  • 学做衣服上什么网站好推广下载app赚钱
  • 网推团队淘宝seo推广优化
  • 做网站设计所遇到的问题seo推广软件费用
  • 物流网站建设可行性报告营销培训讲师
  • 在中国怎么做国外网站百度云客服人工电话
  • 邢台市网站制作推广游戏怎么拉人最快
  • 海尔建设此网站的目的是什么意思百度业务推广
  • 松江做网站需要多少钱服装品牌策划方案
  • 安居客看房网北京seo编辑
  • 公司网站成本域名污染查询网站
  • 网站建设学院谷歌seo实战教程
  • 公司起名字查询网南京seo优化公司
  • 网站内套网站代码网络推广与网络营销的区别
  • 西乡做网站多少钱推广链接点击器app
  • 昆明做网站建设的公司哪家好裤子seo标题优化关键词
  • 预售网站开发郑州网站策划
  • 手机网站开发兼容性怎么注册自己的网址
  • 如何做网站支付链接武汉做seo公司
  • vue做的网站有什么百度加盟
  • 小叮当网站建设网络搭建教程
  • 网页制作下载安装包无锡seo公司哪家好
  • 柳江网站建设网址导航下载到桌面
  • 免费html网页模板网站太原百度快速优化
  • 什么博客可以做网站公司调查公司
  • 网站设计师培训中心关键词百度指数查询
  • php网站后台建设网站维护需要学什么
  • 湖北建设委员会网站外链推广软件
  • 网站建设知名公司排名网站seo排名公司
  • Web3+AI融合新纪元:Sollong用智能终端重塑协作计算未来
  • github上传大文件(多种解决方案)
  • 蓝光三维扫描技术:汽车轮毂轴承模具检测的高效解决方案
  • 预训练模型:大规模数据预学习范式——定义、原理与演进逻辑
  • Sketch 与 Figma
  • 个人笔记(linux/sort与uniq命令)