C#里 =>的用法
问题
看到有人写这样的代码,这里的=>让人感到疑惑,我一直以为它是Lambda表达式的写法,跟C++的->
类似,比较好理解,但是明显下面这里的代码不是属于Lambda表达式的范围
// 这里的MaxHealth1和MaxHealth2有什么区别?
public class Health
{
// expression-bodied member property
public int MaxHealth1 => x ? y:z;
// field with field initializer
public int MaxHealth2 = x ? y:z;
};
为了解决这个问题,写下了这篇博客
C#里=>的两种用法
C#里的=>
有两种用法:
- 用于Lambda表达式里,此时的
=>
被称为lambda operator - 用于expression-bodied member
第一种用法
第一种用法,比较好理解,其实就是Lambda表达式的写法,在C# 3到C# 5版本间,=>
只有此种用法。此时的=>
C++的lambda表达式里的->
类似,举个例子:
// 声明一个函数指针的对象, 也就是委托, 其函数签名为string f(Person)
Func<Person, string> nameProjection = p => p.Name;
// 上面这句, 等同于:
Func<Person, string> nameProjection = delegate (Person p) { return p.Name; };
注意这里的Func<T, TResult>
,最后面的代表函数的返回类型,前面的代表函数的参数,Func只是.NET提供的委托模板:
namespace System
{
// Summary:
// Encapsulates a method that has one parameter and returns a value of the type
public delegate TResult Func<in T, out TResult>(T arg);
}
第二种用法
在C# 6的版本里,=>
开始用于expression-bodied members,代码如下:
public int MaxHealth1 => x ? y:z;
而这种语法,是一种Syntax Sugar,上面的代码等同于下面的:
public int MaxHealth1
{
get
{
return x ? y:z;
}
}
所以,上面的MathHealth1和MathHealth2的区别,其实就是C#里Property和Field的区别:
- MaxHealth1是一个Property,设置了getter,每次访问该值的时候,都会调用x?y:z表达式
- MathHeath2是一个Field,它的表达式只会在其初始化时计算一次
其实应该说的很清楚了,再举个例子:
class Program
{
public class A
{
public static int x;//默认初始化为0
public int X1 => x;
public int X2 = x;
}
static void Main()
{
Console.WriteLine(A.x);// 0
A a = new A();
Console.WriteLine(a.X1);// 0
Console.WriteLine(a.X2);// 0
A.x = 5;
Console.WriteLine(a.X1);// 5
Console.WriteLine(a.X2);// 0
A.x = 10;
Console.WriteLine(a.X1);// 10
Console.WriteLine(a.X2);// 0
}
}
可以看到,每次去取X1的值的时候,都会执行return x;
这个表达式,所以上面的问题解决了。
参考资料:
https://stackoverflow.com/questions/290061/what-does-the-syntax-in-c-sharp-mean/290063#290063
https://stackoverflow.com/questions/31764532/what-is-the-assignment-in-c-sharp-in-a-property-signature
一个小问题
写这个类的时候,编译报了错:
public class A
{
public int x;//默认初始化为0
public int X1 => x;//这一句是OK的
public int X2 = x;// 这一句编译报错
}
报错的信息如下:
A field initializer cannot reference the nonstatic field, method, or property
意思是,一个类里的field不可以用非static的field、method或property进行初始化,也就是说类里field要用静态成员或函数才可以为其初始化。
原因是,在C#里规定,不可以用一个instance variable作为另外一个instance varialble的初始值,因为这里无法保证哪一个变量是先初始化的。
顺便提一句,有意思的是,在C++里,类似的代码是可以运行的,因为C++里类的成员变量是按照声明顺序进行初始化的,代码如下:
#include <iostream>
class T
{
public:
int c = a;// 可以成功编译和运行
int a = 3;
int b = a;
};
int main()
{
T t;
std::cout << t.a << std::endl;// 3
std::cout << t.b << std::endl;// 3
std::cout << t.c << std::endl;// undefined
std::cin.get();
}
C#的Property和Field
之前看过书做过记录,这里复制粘贴一下:
在C++中,为了安全,对于一个类的数据成员,往往是将其设置为private,然后使用对于的Get和Set功能的API去调用和写入值,在C#中,可以通过Field和Property来实现对应的功能,用一句最简单的话就是,Properties expose fields,Property是field的接口,如下述代码所示:
public class MyClass
{
// this is a field. It is private to your class and stores the actual data.
private string _myField;
// this is a property. When accessed it uses the underlying field,
// but only exposes the contract, which will not be affected by the underlying field
public string MyProperty
{
get
{
return _myField;
}
set
{
_myField = value;
}
}
// This is an AutoProperty (C# 3.0 and higher) - which is a shorthand syntax
// used to generate a private field for you
public int AnotherProperty{get;set;}
}
注意:field成员一般(或者说总是)被声明为private,C#3.0以后支持只写Property而不用在类里再写一个private的field,会自动生成对应的field
更多详情可以参考StackOverflow
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)