2

作为 C# 的新手,我试图弄清楚为什么我必须放置CardNumber诸如 static 以适应格式化字符串....

如果我没有添加static string CardNumber而是使用string CardNumber;,代码会报错,最后一个CardNumber下划线。错误发生:字段初始值设定项无法引用非静态字段、方法或属性 'WriteXML.CardNumber'

我知道那里有大量静态和非静态的评论和问题。他们似乎都没有直接解释,“如果在格式化字符串中使用非静态,那么_ 将会发生,或者然后 _将没有任何意义”。如果重复,请至少指出资源。对此,我真的非常感激!

class WriteXML
{
    static string CardNumber;
    static string ExpMo;
    static string ExpYr;
    static string FirstName;
    static string LastName;
    string xmlContent =
        string.Format("<CardNumber>{0}</CardNumber>" +
        "<ExpMo>{1}</ExpMo>" +
        "<ExpYr>{2}</ExpYr>" +
        "<FirstName>{3}</FirstName>" +
        "<LastName>{4}</LastName>", 
            CardNumber, ExpMo, ExpYr, FirstName, LastName);
}
4

4 回答 4

7

字段初始化程序在对象完全构造之前运行,因此它们无法访问同一对象中的其他字段,因为这些字段可能尚未初始化。不保证字段初始化程序的运行顺序。

例如,如果你有类似的东西:

public class Foo
{
    string someField = "foo";
    string someOtherField = someField + "bar";
}

然后在初始化someOtherField之前不能someField进行初始化。

因此someOtherField,一旦构造了对象并且所有字段初始化程序都已运行,您就必须在其他地方进行初始化。一个地方是构造函数:

public class Foo
{
    string someField = "foo";
    string someOtherField;   // can't initialize yet

    public Foo()
    {
        someOtherField = someField + "bar";
    }
}

另一种选择,特别是如果someOtherField不应该是可写的,是使用属性:

public class Foo
{
    string someField = "foo";
    )string SomeProperty
    {
        get { return someField + "bar"; }
    }
}

这将推迟计算出什么SomeProperty,直到您实际尝试访问它,并且作为奖励,如果在构造后someField更改,那么将自动同步到新值。SomeProperty

例如:

var f = new Foo();
Console.WriteLine(f.SomeProperty);   // displays "foobar"
                                     // assuming we'd marked it public
f.someField = "la";                  // assuming we'd made that public  too!
Console.WriteLine(f.SomeProperty);   // displays "labar"
于 2015-07-30T17:56:49.657 回答
3

这个问题的答案可以在 C# 语言规范中找到:

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

在下面的代码中,xmlContent是一个实例字段,它具有一个变量初始化器,而不是引用实例成员CardNumber、ExpMo、ExpYr、FirstName、LastName当您省略静态字段修饰符时,它们是实例成员。所以它不符合规范,因此编译时错误。

string xmlContent =
        string.Format("<CardNumber>{0}</CardNumber>" +
        "<ExpMo>{1}</ExpMo>" +
        "<ExpYr>{2}</ExpYr>" +
        "<FirstName>{3}</FirstName>" +
        "<LastName>{4}</LastName>", 
            CardNumber, ExpMo, ExpYr, FirstName, LastName);

请参阅@Matt Burland 的回答如何解决此问题。

于 2015-07-30T18:56:08.827 回答
1

我不确定您要实现什么,但也许这段代码会对您有所帮助。

public class Foo
{
    string CardNumber { get; set;}
    string ExpMo { get; set; }
    string ExpYr { get; set; }
    string FirstName { get; set; }
    string LastName { get; set; }

    public String WriteXml()
    {
        string xmlContent =
        string.Format("<CardNumber>{0}</CardNumber>" +
        "<ExpMo>{1}</ExpMo>" +
        "<ExpYr>{2}</ExpYr>" +
        "<FirstName>{3}</FirstName>" +
        "<LastName>{4}</LastName>",
        CardNumber, ExpMo, ExpYr, FirstName, LastName);

        return xmlContent;
    }
}
于 2015-07-30T18:00:36.957 回答
1

我将尝试引用并完成您想要的解释语句:

如果在格式化字符串中使用非静态引用(更一般地说,在另一个非静态字段中),那么该字符串/字段将无法访问它,因为它首先需要对初始化对象的引用(非-static 意味着它可以根据字段所在的不同对象具有不同的值)。使用静态字段,它可以随时访问而无需初始化对象。

于 2015-07-30T18:19:25.897 回答