如果我想为返回任务的非异步方法保留这一点。
public static Task CompletedTaskA { get { return Task.CompletedTask; } }
public static Task CompletedTaskB { get; } = Task.CompletedTask;
在任何情况下,应该优先选择其中一种吗?或者它们是一样的?我也想知道字符串和基本上我对属性所做的任何事情都是一样的,比如:
get {return "some string"; }
与{ 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
}
我的意图是将一个已完成的任务保存在一个字段中(在这种情况下,我选择了一个只读属性(,并继续使用它来满足任务返回。我想知道上面的例子中是否有一个一直在使用相同的已完成任务,而另一个每次都在要求另一个已完成任务?
如果您转到SharpLab并查看以下代码:
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()
{
}
}
这一直延续到IL级别。由于Greeting_2
由成员变量支持,该变量在构造函数中初始化。
在您的Task.CompletedTask
示例中,您最终得到的是:
public static Task CompletedTaskB { get; } = Task.CompletedTask;
缓存Task
,而:
public static Task CompletedTaskA { get { return Task.CompletedTask; } }
每次调用Task
中的CompletedTask
对象。事实上,这将由JIT内联。这种方法还有一个优点,即不向类中添加额外的(隐藏的(成员变量,如果您有很多实例并且担心内存使用,这可能会成为一个问题。
它们不一样。每次访问属性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";
和
get {return "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方法而不进行赋值,则不会创建backing字段,也不会向构造函数添加任何工作。
对于字符串或任何其他类型都是如此。如果为属性赋值,则构造/获取该值的工作将被放入类的构造函数中。如果您在get方法中创建了值,那么工作就会被放入get方法中。