首页 > 解决方案 > c#中声明对象的方法

问题描述

我学了一点 C#,有一部分让我感到困惑。这就是我们如何声明对象。我通常使用 声明对象FormGame frm = new FormGame(),但我发现还有更多。

这些是示例:

var frm = new FormClothes();

Excel._Worksheet worksheet = (Excel.Worksheet)excelApp.ActiveSheet;

你们能解释一下区别,技术的名称以及它是如何工作的吗?您可以添加更多声明对象的方式示例,这将对我和其他学习者有所帮助。

也许,你们中的一些人可能很难理解我所说的“技术名称”是什么意思。所以,我试着解释一下。例如:new AddRecord()。我将其命名为“调用类而不声明对象”。如果您在访问修饰符前面添加静态(公共静态.....),您可以做到这一点。

标签: c#object

解决方案


我们并没有真正使用“声明对象”这个短语。谈论“声明变量”会更常见:

FormGame f;

这声明了一个名为的变量,该变量f能够保存 FormGame 类型的对象实例或其后代之一。

var没什么特别的——它只是给编译器的一条指令“我希望你弄清楚正在分配什么类型的对象并自动使 f 变量成为那种类型”。要解决它,需要有一个任务。你不能说:

var f;

它必须在右边有一些东西,以便编译器可以猜测类型:

var f = new FormGame();

只有当阅读代码的人(可能不是您)很明显正在创建什么类型的对象时,您才应该尝试使用 var。这些很好,减少了混乱:

var formattedStr = something.ToString();
var dict = new Dictionary<string, int>();

还行吧:

var s = "a string";

这可能不太好:

var res = process.GetResult();

Intellisense 和 Visual Studio 将能够解决这个问题,这就是为什么你到处都能看到 var 并且被过度使用的原因,但如果我们无需在 Visual Studio 中指向某些东西就可以读取/知道类型,它通常会使代码更具可读性和更快地理解并等待工具提示告诉我们它是什么类型

有时 var 会让你失望,而var'ing 声明意味着你最终会猜测继承层次结构中的类型。例如r,这里被猜测为 type object,这是 c# 中所有事物的基础,这使得代码在没有强制转换的情况下非常不可用:

foreach(var r in dataTable.Rows) 

如果我们是具体的,它可以正常工作:

foreach(DataRow r in dataTable.Rows)

new当我们使用关键字时,我们谈论“创建对象”或“创建实例” 。我们通常将实例分配给一个变量,但并非总是如此:

f = new FormGame(); //make a new instance and assign to a previously declared variable

我们不必分配给变量:

new FormGame().ShowDialog(); 

这将创建一个 FormGame 的新实例并显示它,但是我们无法到达该对象以对其执行任何其他操作 - 在这一行代码之后它就丢失了

我们不必使用new关键字来给变量赋值:

f = otherForm;

这分配了一个值,但我们没有在这里创建任何新对象,我们只是指向f内存中我们otherForm所指向的同一个对象。如果您使用变量 f 更改有关对象的一件事,则另一个变量也会看到更改:

otherForm.Text = "Hello"; 
MessageBox.Show(f.Text); //shows Hello

您分配 excel 工作表变量的示例也是这种形式;它不是在制造任何新事物,而是采用现有事物并将其分配给变量。在您的情况下,涉及转换,但转换不会创建新对象,它会更改现有对象的表观类型。我说明显类型是因为它不会改变对象的实际类型,只会改变它的外观。字符串始终是字符串,不能转换为 int:

string s = "123";
int x = (int)s; // no

但是因为 string 是 object 的后代,所以可以将它分配给 object 类型的变量:

object o = s; // works ok

要取出字符串,您必须从看起来像父类型的东西变成需要强制转换的子类型:

string t = (string)o; //only works if o really is holding a string or a descendant of string

这个分配没有一个是创建一个新对象 - 即使它被施放,它也是相同的“123”转来转去


在创建对象实例时,您的代码可能不会使用new,但您使用的代码可能会使用

SomeClass x = classFactory.Create();

在这里,我们有一个对象,其工作是制造新对象。我们没有new在代码中使用关键字,但类工厂可能使用了。我们还在一行中声明了变量 x 并将 x 的值全部赋值。您可能会遇到这种代码模式,尤其是在反射中,您要求另一个类为您创建一个新实例,而不是使用 new。拥有一个新事物的方法或属性 Male 会有所帮助,这样您就可以获得有关您正在创建的内容的一些信息。如果我们考虑一下日期时间:

DateTime x = DateTime.Now;
DateTime y = DateTime.UtcNow;

在这里,它使用静态(我稍后会谈到)和命名属性来制造对象。现在调用将创建一个日期时间,它是本地时区的当前时间。调用 UtcNow 会创建一个日期时间,它是 UTC 中的当前时间。Microsoft 肯定可以做到,因此您必须这样做:

DateTime x = new DateTime(DateTimeKind.Local);
DateTime y = new DateTime(DateTimeKind.Universal);

但这很罗嗦,需要开发者记住“当我使用带有 DateTimeKind 参数的构造函数时,返回的日期时间将是当前时间”

总而言之,使用这些名为 Now 和 UtcNow 的便利属性为我们制造新对象,它们简洁明确地告诉我们他们创造了什么样的东西


静态略有不同。最好将其视为编译器无形地为您执行 new 并将其分配给与类同名的全局变量的场景

DateTime d = DateTime.Now;

这声明了一个名为 d 的日期时间变量。它静态访问 DateTime 的 Now 属性 - 这意味着您无需创建新的 datetime 即可调用 Now 属性。

如果你很难理解静态,想象在某个地方有一个 DateTime 对象的实例,它被称为 DateTime。它是“无形地创造的”和“随处可见的”。想象一下编译器为你写了这样的东西:

global DateTime DateTime = new DateTime();

当然,它实际上不会以这种方式发生,但这样思考可能会帮助您理解静力学;想象那行代码发生在你看不到的地方


推荐阅读