【问题标题】:What exactly is this "variable"/"instantiation" in the example code i made?我制作的示例代码中的这个“变量”/“实例化”到底是什么?
【发布时间】:2018-07-22 07:25:05
【问题描述】:

所以我对类及其变量有一些疑问,主要是关于“消息消息”;在我之前写的代码中。

我的主要问题是:为什么我可以在类范围内声明这个 Message message; 而我不需要将它放在方法范围内?因为我 THINK 一个实例化需要放在一个方法中,另外,这个Message message;到底是个什么变量?是实例化吗?

public class Message
{
    public string MessageValue() => "Hello World";
}
public class Write
{
    Message message;
    private void printMessage() => Console.WriteLine(message.messagevalue());
}

【问题讨论】:

  • Why i can declare this "Message message;" in the class scope and i don't need to put it in a method scope? 在 C# 中的术语是 field。它是一个作用域为类的实例而不是方法的变量。我怀疑你意味着使用Message message = new Message();,否则你会得到一个异常,因为messagenull(未实例化)。
  • 您开发了一个引用类型 Message 的字段。但是您还没有在该字段中创建实例。它具有空初始值。因此,您的 WriteLine 将抛出 NullPointerException。
  • 您需要将“messagevalue()”设置为静态方法才能像上面一样调用它。您声明一个为空的变量并调用一个非静态的方法!

标签: c# class variables instantiation


【解决方案1】:

有几件事要记住。 Message 在您的示例中是 typemessage 是实际字段或变量的名称。

变量声明

Message message;

您基本上是在声明变量的类型和名称(也可以是 Message foo)。

实例化

new Message();
SomeMethod(new Message());

我们正在创建Message 的新实例。然后,我们使用赋值来存储新实例以保持它。

在第二个示例中,我们将 Message 的新实例传递给期望它的类,即使我们没有将它保存到变量中。

作业

message1 = message2;

非常不言自明。

一次性

Message message = new Message(); 

我们正在执行上述所有操作。我们正在创建变量,说明什么类型,然后创建一个新实例。这是很常见的。太常见了,以至于人们厌倦了将Message 写三遍,因此 C# 添加了一种新语法,它的作用实际上是相同的,没有区别:

var message = new Message();C# 可以分辨出message is supposed to be and will make message` 那个类型是什么类型,所以我们不必多余。

关于需要在方法中的实例化,您的预感实际上是正确的。

在做

public class Foo
{
    public Message message = new Message();
}

是完全有效的 C# 语法,可以正常工作并且可以编译。然而,它在幕后所做的实际上是这样的:

public class Foo
{
    public Message message;

    public Foo() 
    {
        message = new Message();
    }
}

这实际上给我在 Unity 中工作时带来了问题。在 Unity 中,如果创建的对象继承自 MonoBehavior,则不再允许使用构造函数创建它,并且它会以某种方式完全绕过对构造函数的调用。这真的很烦人,而且让事情变得更加复杂。

其中一个复杂因素是这些字段初始值设定项从未被调用,所以我得到空引用异常而没有意识到如何。我花了一段时间才弄清楚。

现在我必须手动将其放入 Unity 在创建对象时调用的 Awake() 方法中,基本上是编译器会做的。

编辑:正如 Thomas Schremser 指出的,var 仅在方法内部有效。

为了更清楚起见,Message message; 是字段减速(如果在函数内部,则为变量减速),其中 Message 是类型,message 是字段/变量。语法为Type memberName = new Type()

字段是属于类的变量,要么属于类实例,要么属于类本身。例如:

public class Foo
{
    public class int InstanceField;   // This belongs to individual instances
    public static int StaticField;    // This belongs to the class itself 
                                      // (accessed via Foo.StaticField)
    public var ImplicitlyType = 3;    // ERROR: Fields can't be implicitly typed

    public void Bar()
    {
        int notAField;           // This is only accessible in this function,
                                 // Making it a local variable, not a field
        var implicitlyType = 4;  // This works because implicitlyTyped is a local variable
                                 // It's type is also of int, not var
    }
    public void Baz(int alsoNotAField)
    {
        // alsoNotAField is a parameter. It's value will be given from other methods
        // alsoNotAField is also only usable in the scope of this method
        notAField++; // ERROR: notAField can't be used here, because it's limited to Bar()
        
    }
}

字段是属于类的一类变量,方法是属于类的一类函数。

函数之外的变量称为字段,在 C# 中无法在类之外拥有函数。所以,从某种意义上说,C#只有方法。

【讨论】:

  • 好答案。但是由于 OP 谈到了字段,因此值得一提的是 var 不适用于它们。
  • 非常感谢您在这里澄清了很多事情,但我在另一条评论中也看到了“消息消息;”那么是一个字段吗? (您可以通过变量 message 访问 Message 类中的不同属性和值)
  • 谢谢你们,我用更多信息更新了我的答案。
【解决方案2】:

让我们看一下 write 类并深入研究它:

public class Write
{
    Message message;
    private void printMessage() => Console.WriteLine(message.messagevalue());
}

Message message; 是一个字段,它的作用域是一个名为 message 的类的实例。

字段的定义来自Microsoft docs

字段是直接在类中声明的任何类型的变量 或结构。字段是其包含类型的成员。

意思是messageMessage类的字段类型,可以通过Write类访问Message类。

例如:

Write write = new Write();
write.message = new Message();
message.messagevalue();

【讨论】:

  • 那么字段和变量之间的主要区别是,在字段中您可以从字段的类型中操作方法和值吗? (这将是一堂课)(非常感谢你)
  • @LucasMella 不完全是。首先,字段和变量不是对立的,正如 MS 文档所说,字段是变量,只是位置不同。使变量成为字段的原因是它是否在类的主体中声明。如果它在函数中声明,它只是一个变量。您不能从函数外部访问该变量,即使在同一个类中也不行,但是,如果它是公共字段,则可以。我不确定您所说的“in the field”是什么意思。所有字段都是内存地址。变量也可以操纵它所属类型的方法和值。
  • 而且它们都不必在一个类中,它也可以是一个结构。主要区别在于它们的编写位置和访问位置。
猜你喜欢
  • 1970-01-01
  • 2021-08-12
  • 1970-01-01
  • 2011-07-04
  • 2015-11-19
  • 1970-01-01
  • 1970-01-01
  • 2018-08-04
  • 1970-01-01
相关资源
最近更新 更多