cod*_*nix 17 .net c# initialization readonly c#-3.0
为什么我不能初始化初始化程序中的只读变量?以下内容不起作用:
class Foo
{
public readonly int bar;
}
new Foo { bar=0; }; // does not work
Run Code Online (Sandbox Code Playgroud)
这是由于CLR的某些技术限制吗?
编辑
我知道它new Foo { bar=0; }
是相同的new Foo().bar=0;
,但是CLR强制执行"readonly",还是仅仅是编译器限制?
Dav*_*vid 17
初始化程序只是语法糖.当你写:
new Foo { bar=0; };
Run Code Online (Sandbox Code Playgroud)
(顺便说一句,这是一个语法错误,应该是这个...)
new Foo { bar=0 }
Run Code Online (Sandbox Code Playgroud)
实际发生的是:
var x = new Foo();
x.bar = 0;
Run Code Online (Sandbox Code Playgroud)
由于该属性是只读的,因此该第二个语句无效.
编辑:根据您的编辑,问题有点不清楚.根据readonly
设计,财产不可设置.它建立在对象构造上.这由编译器和运行时强制执行.(不可否认,我没有对后者进行过测试,因为绕过前者需要一些技巧.)
请记住,有两个阶段的"编译".在将C#代码编译为IL代码时强制执行,并在将IL代码编译为机器代码时强制执行.
这不是CLR的技术限制,它的工作正是因为它应该给出明确的readonly
声明.构造对象后,您无法设置readonly
属性.
小智 14
允许readonly
在初始化程序中设置a 会引入在编译时无法实施的矛盾和复杂性.我想这个限制是为了避免含糊不清.最关键的是编译时验证.
想象一下:
class Foo
{
public readonly int bar;
Foo () {
// compiler can ensure that bar is set in an invoked ctor
bar = 0;
}
}
// compiler COULD know that `bar` was set in ctor
// and therefore this is invalid
new Foo { bar = 0; }
Run Code Online (Sandbox Code Playgroud)
现在,考虑一下:
class Foo
{
public readonly int bar;
Foo () {
// imagine case where bar not set in ctor
}
}
// compiler COULD know that `bar` is not bound yet
// therefore, this COULD be valid
new Foo { bar = 0; }
// but this COULD be proved to never be valid
new Foo();
Run Code Online (Sandbox Code Playgroud)
想象一下,上述两种情况都是统一的(例如,"通过编译器魔术"),但是,请输入泛型:
T G<T> () where T : new
{
// What in heck should happen *at compile time*?
// (Consider both cases above.)
// What happens if T (Foo) changes to include/not-include setting the
// readonly variable in the ctor?
// Consider intermediate code that invokes G<Foo>() and this other
// code is NOT recompiled even though Foo is--
// Yet a binary incompatibility has been added!
// No thanks!
return new T();
}
G<Foo>();
Run Code Online (Sandbox Code Playgroud)
我相信我概述的案例显示了使用"动态" readonly
方法的一些复杂性,并且在一天结束时,我认为它仅仅是一种选择的语言限制(编译器实现语言)来强制/允许编译时验证.
C# 9.0 最终为我们带来了仅限 init 的属性设置器:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/init
struct Point
{
public int X { get; init; }
public int Y { get; init; }
}
var p = new Point() { X = 42, Y = 13 };
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
13639 次 |
最近记录: |