需要解释一下初学者C#代码。

5

我开始学习C#。我尝试声明一个类和一些变量,并尝试对字符串进行简单的连接。但是我遇到了一些错误-以下是代码:

namespace ConsoleApplication1
{
    class Class1
    {
        string s1 = "hi";
        string s2 = "hi";
        string s3 = s1 + s2;
    }
}

我得到的错误是- 字段初始化程序不能引用非静态字段、方法、属性 'ConsoleApplication1.Class1.s1' 有人能解释一下这里发生了什么吗?
谢谢。
3个回答

15

有人能解释一下这里发生了什么吗。

好的,一旦你理解了术语,编译器错误消息就已经说明了一切。这行代码是无效的:

string s3 = s1 + s2;

你正在声明实例变量,而实例变量初始化程序(例如这里的 s1 + s2)不允许引用正在创建的实例中的其他字段 - 或者实例本身。请记住,上述声明等同于:

string s3 = this.s1 + this.s2;

来自C# 4规范第10.5.5.2节:

 

实例字段的变量初始化器不能引用正在创建的实例。因此,在变量初始化器中引用this是一个编译时错误,因为在变量初始化器中通过简单名称引用任何实例成员都是编译时错误。

(无可否认这是规范中比较奇怪的措辞之一...)

您必须将逻辑放入构造函数体中:

class Class1
{
    string s1 = "hi";
    string s2 = "hi";
    string s3;

    public Class1()
    {
        s3 = s1 + s2;
    }
}

8

变量没有特定的逻辑初始化顺序。最好设计程序,使其能够在变量初始化的任何顺序下正常工作。

对于本地变量的非平凡赋值,您可以使用该类型的构造函数:

class Class1
{
    string s1 = "hi";
    string s2 = "hi";
    string s3;

    public Class1()
    {
         s3 = s1 + s2;
    }
}

7
这是不正确的。根据我手头拿到的C# 4规范第10.5.5节:“同样地,当创建一个类的实例时,该实例中的所有实例字段首先被初始化为它们的默认值,然后按文本顺序执行实例字段初始值设定项。”(强调我的)。 - Jon Skeet
@JonSkeet 我修改了措辞。从概念上讲,无论实现是否具有顺序,最好将其开发为无序的。 - Servy
这可以很容易地通过调试器进行确认。我在自己的代码中确实注意到了实例字段初始化的行为。 - Chris
@Servy:我引用的不是实现细节,而是规范。请参见第10.5.5.2节。我同意最好不要使用它,因为它会使代码变得脆弱 - 但它是明确定义的(除非您使用部分类,在那里“文本顺序”未定义)。还要注意,静态初始化程序没有此限制。 - Jon Skeet
2
@JonSkeet:我想起了常被归于亚伯拉罕·林肯的不朽名言:如果你把羊尾巴叫做腿,那么羊有几条腿? 四条;把尾巴叫做腿并不能使它成为腿。 - Eric Lippert
显示剩余2条评论

6
尝试在一个方法中初始化s3,最好是在构造函数中。
class Class1
{
    string s1 = "hi";
    string s2 = "hi";
    string s3;


    public Class1()
    {
        s3 = s1 + s2;
    }
}

3
这里的问题不在于执行“算术运算”(字符串连接)本身,而在于它隐式地使用了“this”。 - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接