嗨,我是 C# 的新手,我知道在表面上我不能在静态方法中使用非静态字段。但我有一个我试图从概念上理解的情况。
查看此代码片段:
class CIMConversionHelper
{
private static Logger Logger = LogManager.GetCurrentClassLogger();
private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();
public static TDX2KlarfResult HandleConversion(TDXProcessItem item, string fileName)
{
TDX2KlarfResult result = new TDX2KlarfResult();
result.success = true;
XmlDocument doc = new XmlDocument();
try
{
doc.Load(fileName);
}
catch (Exception ex)
{
result.success = false;
Logger.Error(ex, "XML Parsing Error: ");
return result;
}
_procEndTimeData.ToolType = toolType;
_procEndTimeData.Lot = input.cimToolContext.LOT;
_procEndTimeData.WaferScribe = input.cimWaferContainer.waferContext.WAFER_SCRIBE;
_procEndTimeData.Processing_End_Time = input.cimToolContext.PROCESSING_END_TIME;
}
public static TDX2KlarfResult Convert(TDXProcessItem item, string fileName)
{
TDX2KlarfResult result = new TDX2KlarfResult();
result.success = true;
try
{
result = CIMConversionHelper.HandleConversion(item, fileName);
}
catch (Exception ex)
{
// Failed to Parse the xml Not good mark nonrecoverable error and return.
result.errorType = "Non-Recoverable";
result.success = false;
Logger.Error(ex, "Unknown Error: ");
return result;
}
if (result.success)
{
//DBHelper.AddProcessingEndTimeToDB();
}
return result;
}
}
这是一个非常精简的片段,但抓住了我的问题。我创建了一个对象引用作为名为 _procEndTimeData 的 ProcessingEndTimeData 字段。
那么为什么它在Visual Studio中告诉我: "非静态字段、方法或属性CIMConversionHelper._procEndTimeData是否需要对象引用?
我想我应该能够为静态函数"HandleConversion"内第 4 行中的声明对象"_procEndTimeData"赋值
有人可以向我解释为什么这个参考还不够吗?为什么我必须在静态函数 HandleCOnversion 中创建另一个 ProcessingEndTimeData 对象?
我知道我可以将_procEndTimeData切换为静态,但是如果我已经在字段级别创建了引用,为什么还需要这样做呢?
想想设备的内存。
创建对象时,将为其保留内存。想象一下,由于它的属性(int,char...),它占用了32个字节。如果创建 10 个对象,则对象的内存中将占用 320 个字节。
但是,当您使用"static"时,这些属性仅为类创建一次。对于您创建的每个对象,不要一次。
因此,您的 10 个对象可以访问它们自己的属性(int、char...)以及静态属性。但是从"静态"方法中,您无法访问该类对象的属性,因为您没有它的实例。
一个非常简单的示例:您有一个具有 Name 属性的 User 类。添加整数类型的静态变量:静态整数计数。该变量将用于记录您创建的用户数。 在用户的构造函数中,您可以执行count++,因为类的实例可以访问类的属性。但是,如果您创建一个静态方法:
public static void DoSomething()
{
// You can show a message with the number of users
MessageBox.Show(count.ToString());
// But you CAN'T access to a "Name" because this method is not
// a method of one concrete user. It's a general method, for all users
}
如果你调用DoSomething,并且你创建了两个用户,"Tom"和"Jerry",在DoSomething中你不认识任何用户。
您有 2 个选择来完成这项工作。不确定哪一个适用。我的猜测是我将展示的第一个
private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();
更改为
static private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();
这说明这个字段也是静态的,即属于类,而不是CIMConversionHelper类的实例。
另一种选择,我认为您不希望它在该方法中创建 CIMConversionHelper 的实例。正如我所说,这可能不是你想要的。
如果你的意图是这个类(CIMConversionHelper)都是静态的,即你永远不会创建它的实例,那么将类本身标记为静态,编译器将确保你不会意外地创建非静态成员。
static class CIMConversionHelper{....}
为什么会这样?
你说你在这里创建了一个参考
private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();
你还没有创建它。
您需要了解静态函数和实例函数和字段之间的区别。
让我们举个例子。我们有一个类 Thingy。它包括一个工厂方法,可以制作thingy实例并记录它制作了多少个实例。
public class Thingy{
static s_thingyCount = 0;
string _froop;
public static CreateThingy(){
var thing = new Thingy();
......
s_thingyCount++;
thing._froop = "hello";
return thing;
}
public void Twang(int froop){
......
}
public int Oink(string pling){
......
_froop = pling;
}
}
我们可以去
var t1 = Thingy.CreateThingy();
t1.Oink("Ole");
CreateThingy 不对类的实例进行操作,而是对类本身进行操作。count 变量不属于实例,它属于类本身。请注意,在创建方法中,我们必须说
thing._froop = "hello";
即我们要设置哪些对象_froop(我们正在制作的对象)。
var t1 = Thingy.CreateThingy();
现在我们有一个 Thingy 的实例,我们可以对其调用方法
t1.Oink("Ole");
查看该方法
public int Oink(string pling){
......
_froop = pling;
}
我们不说要设置哪个froop,我们正在操作类的一个实例。
我们不能做
Thingy.Oink("xxx");
哪个是更新?我们也不能这样做
Thingy._froop = "fff";
出于同样的原因
但我们可以做到
var count = Thingy.s_thingyCount;
这如何映射到您的类。 这是静态的。它就像CreateThingy一样,它没有要操作的实例。
public static TDX2KlarfResult HandleConversion(TDXProcessItem item, string fileName)
但是你这样做
_procEndTimeData.ToolType = toolType;
使用此字段
private readonly ProcessingEndTimeData _procEndTimeData = new ProcessingEndTimeData();
这就像做
_froop = "hello"
in CreateThingy
_proceEndTimeData仅存在于类的实例中。
当你这样做时,它将被创建
new CIMConversionHelper();
但我怀疑这不是你想做的。所以你需要_proceEndTimeData静态的,就像s_thingyCount
如果我理解正确,你回答自己:"我知道在表面上我不能在静态方法中使用非静态字段",然后你在方法中声明了一个非静态变量:
私有只读处理结束时间数据_procEndTimeData
它应该是静态的,如果需要,除了只读。
其原因与面向对象编程有关。若要从类访问静态方法,无需实例化它。这就是为什么不能从该类的静态方法中引用类级非静态变量的原因。希望这让它更清楚一点。
我可以将_procEndTimeData切换为静态,但是如果我已经在字段级别创建了引用,为什么还需要这样做?
你没有创建这样的东西,你的_procEndTimeData
是每个CIMConversionHelper
实例中的一个字段,你没有。
如果它可以帮助您更好地可视化问题,请想象一下,如果您的期望是现实并且您有以下代码,会发生什么:
CIMConversionHelper h1 = new(), h2 = new();
CIMConversionHelper.Convert(.....whatever....);
它会改变h1._procEndTimeData
吗?h2._procEndTimeData
?它必须选择一个,对吧?那么它选择哪一个呢?
不。static
方法只能使用static
字段、句点。