C# 在get中返回值与指定属性之间有什么区别?
如果我想为返回任务的非异步方法保留这个便利C# 在get中返回值与指定属性之间有什么区别?,c#,.net,asynchronous,properties,task,C#,.net,Asynchronous,Properties,Task,如果我想为返回任务的非异步方法保留这个便利 public static Task CompletedTaskA { get { return Task.CompletedTask; } } public static Task CompletedTaskB { get; } = Task.CompletedTask; 在任何情况下,其中一个应该优先于另一个吗?或者它们是一样的?我还想知道字符串和基本上我对属性所做的任何事情也是如此,例如: get{return“some string”;}v
public static Task CompletedTaskA { get { return Task.CompletedTask; } }
public static Task CompletedTaskB { get; } = Task.CompletedTask;
在任何情况下,其中一个应该优先于另一个吗?或者它们是一样的?我还想知道字符串和基本上我对属性所做的任何事情也是如此,例如:
get{return“some string”;}
vs{get;}=“some string”代码>
编辑:我想澄清我对上述道具的使用。我有几个事件处理程序,它们将Task作为返回类型,由我正在使用的库提供给我。此类事件的一个示例:
private Task Client_MessageReceived(Message message)
{
Task.Run(async ()=> await HandleMessageReceived(message));
// here is where i would use it
return CompletedTask; // A OR B?
}
private async Task HandleMessageReceived(Message message)
{
// Do stuff with message that might take long and block the handler
}
我的意图是将已完成的任务保存在一个字段中(在本例中,我选择了一个只读属性),并继续使用它来满足任务返回。我想知道上面的例子中是否有一个一直在使用同一个已完成的任务,而另一个每次都要求另一个已完成的任务?它们不一样。
每次访问时都会调用properties get方法。默认情况下,创建属性时,属性后面会有一个隐藏字段,以便:
public static Task CompletedTaskB { get; set; }
将在幕后实际生成:
private static Task _completedTaskB;
public static Task CompletedTaskB
{
get {
return _completedTaskB;
}
set {
_completedTaskB = value;
}
}
分配属性=Task.CompletedTask时,您正在设置其初始值,该值等效于:
_completedTaskB = Task.CompletedTask;
然后,当您访问该属性时,它将从私有字段读取
我注意到,您将其定义为只读(只有getter而不是setter),因此您将无法分配变量。相反,您必须使用:
public static Task CompletedTaskA { get { return Task.CompletedTask; } }
这将始终返回Task.CompletedTask
一般而言,以下各项之间的差异:
{ get; set; } = "some string";
及
第一个是初始赋值,而后一个是在访问属性时调用的方法。当您在定义中为属性权限赋值时,一些“魔法”在幕后发生。
编译器创建一个隐藏的支持字段,并在类的构造函数中将该值分配给该支持字段
换句话说,您可以认为下面的两个类以相同的方式工作
class AssignedImplicit {
public string Prop {get;} = "example";
}
class AssignedExplicit {
private readonly string Prop_BackingField;
public AssignedExplicit() {
Prop_BackingField = "example";
}
public string Prop { get { return Prop_BackingField; } }
}
如果只定义get方法而不进行赋值,则不会创建支持字段,也不会向构造函数添加任何工作
这适用于字符串或任何其他类型。
如果为属性赋值,则构造/获取该值的工作将放入类的构造函数中。如果在get方法中创建值,则工作将放入get方法。如果转到并查看以下代码:
public class C
{
public void M()
{
}
public string Greetig_1
{
get{return "hello";}
}
public string Greeting_2{get;} = "hello";
}
您可以看到,Greeting_2
由一个成员变量支持:
public class C
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly string <Greeting_2>k__BackingField = "hello";
public string Greeting_1
{
get
{
return "hello";
}
}
public string Greeting_2
{
[CompilerGenerated]
get
{
return <Greeting_2>k__BackingField;
}
}
public void M()
{
}
}
公共C类
{
[编译生成]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
私有只读字符串k\uu BackingField=“hello”;
公共字符串问候语\u 1
{
得到
{
回复“你好”;
}
}
公共字符串问候语2
{
[编译生成]
得到
{
返回k__BackingField;
}
}
公屋
{
}
}
这一直延续到IL水平。由于Greeting_2
由一个成员变量支持,该变量在构造函数中初始化
在您使用Task.CompletedTask
的示例中,您最终得到的是:
publicstatictaskcompletedtaskb{get;}=Task.CompletedTask代码>
缓存任务
,而:
public static Task CompletedTaskA{get{return Task.CompletedTask;}}
每次调用以获取Task
中的CompletedTask
对象。实际上,这将由JIT进行内联。这种方法还有一个优点,就是不向类中添加额外的(隐藏的)成员变量,如果您有很多实例并且担心内存使用,这可能是一个问题。您是否尝试搜索现有的解决方案?这个有很多重复的
public class C
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly string <Greeting_2>k__BackingField = "hello";
public string Greeting_1
{
get
{
return "hello";
}
}
public string Greeting_2
{
[CompilerGenerated]
get
{
return <Greeting_2>k__BackingField;
}
}
public void M()
{
}
}