使用或不使用 C# 'new' 关键字设置对象属性



使用或不使用new关键字设置对象属性有根本区别吗?

下面是一个例子来说明我所指的内容,如案例1和案例2所示。尽可能使用案例2(看起来像一句话),但不能确定C#new关键字是否有任何缺点,例如内存使用率增加@Dennis_E我已经投了+1;-)

修订后的补充:感谢大家的及时评论和回答。你知道,评论和答案会引出一些你在提出问题时从未想过的相关问题。请原谅我的修改,但希望你能理解。

假设案例1和案例2中的代码被多次使用(比如当您导航到视图页面时),案例2在增加内存方面是否有缺点。也许我在这里做了一个错误的假设——"新建"同一个变量会创建一个新对象吗??也许这是根本问题。

public static class MyCache
{
public static NameIdObject MyCacheObject = new NameIdObject();
}
public class NameIdObject
{
public string Name { get; set; }
public int Id { get; set; }
}
// Usage 1: without new keyword
MyCache.MyCacheObject.Name = "foo";
MyCache.MyCacheObject.Id = 123;
// Usage 2: with new keyword
MyCache.MyCacheObject = new NameIdObject { Id = 123, Name = "foo" };

new关键字与设置属性无关。它会创建一个新对象。但是,对象初始值设定项只能与创建新对象结合使用。

声明

MyCache.MyCacheObject = new NameIdObject { Id = 123, Name = "foo" };

是对象初始值设定项。这只是一种更方便的书写方式(相当于):

MyCache.MyCacheObject = new NameIdObject();
MyCache.MyCacheObject.Id = 123;
MyCache.MyCacheObject.Name = "foo";

您的第一个代码示例仅设置属性值。它不实例化新对象。(您可以在前面的单独语句中这样做)
因此,根本区别在于:您正在创建一个新对象。

检查这一点的好方法是编写小文件,编译它们,并使用IL Spy检查它们在中间语言中的作用。如果我对这个案子这么做,我会得到文件。这是C#代码。

using System;
namespace test
{
public class NameIdObject
{
public string Name { get; set; }
public int Id { get; set; }
}
public static class MyCache
{
public static NameIdObject MyCacheObject = new NameIdObject();
}
public static class Program
{
public static void Main()
{
MyCache.MyCacheObject.Name = "foo";
MyCache.MyCacheObject.Id = 123;
}
}
}

情况2

using System;
namespace test
{
public class NameIdObject
{
public string Name { get; set; }
public int Id { get; set; }
}
public static class MyCache
{
public static NameIdObject MyCacheObject;
}
public static class Program
{
public static void Main()
{
MyCache.MyCacheObject = new NameIdObject { Id = 123, Name = "foo" };
}
}
}

当您通过开发人员命令行编译时。看见https://msdn.microsoft.com/en-us/library/78f4aasd.aspx了解更多信息。您可以使用IL Spy 查看中间语言

以下是结果:

案例1

.namespace test
{
.class public auto ansi abstract sealed beforefieldinit test.MyCache
extends [mscorlib]System.Object
{
// Fields
.field public static class test.NameIdObject MyCacheObject
// Methods
.method private hidebysig specialname rtspecialname static 
void .cctor () cil managed 
{
// Method begins at RVA 0x207b
// Code size 11 (0xb)
.maxstack 8
IL_0000: newobj instance void test.NameIdObject::.ctor()
IL_0005: stsfld class test.NameIdObject test.MyCache::MyCacheObject
IL_000a: ret
} // end of method MyCache::.cctor
} // end of class test.MyCache
.class public auto ansi beforefieldinit test.NameIdObject
extends [mscorlib]System.Object
{
// Fields
.field private string '<Name>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
01 00 00 00 00 00 00 00
)
.field private int32 '<Id>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
01 00 00 00 00 00 00 00
)
// Methods
.method public hidebysig specialname 
instance string get_Name () cil managed 
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2050
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld string test.NameIdObject::'<Name>k__BackingField'
IL_0006: ret
} // end of method NameIdObject::get_Name
.method public hidebysig specialname 
instance void set_Name (
string 'value'
) cil managed 
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2058
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld string test.NameIdObject::'<Name>k__BackingField'
IL_0007: ret
} // end of method NameIdObject::set_Name
.method public hidebysig specialname 
instance int32 get_Id () cil managed 
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2061
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 test.NameIdObject::'<Id>k__BackingField'
IL_0006: ret
} // end of method NameIdObject::get_Id
.method public hidebysig specialname 
instance void set_Id (
int32 'value'
) cil managed 
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2069
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 test.NameIdObject::'<Id>k__BackingField'
IL_0007: ret
} // end of method NameIdObject::set_Id
.method public hidebysig specialname rtspecialname 
instance void .ctor () cil managed 
{
// Method begins at RVA 0x2072
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method NameIdObject::.ctor
// Properties
.property instance string Name()
{
.get instance string test.NameIdObject::get_Name()
.set instance void test.NameIdObject::set_Name(string)
}
.property instance int32 Id()
{
.get instance int32 test.NameIdObject::get_Id()
.set instance void test.NameIdObject::set_Id(int32)
}
} // end of class test.NameIdObject
.class public auto ansi abstract sealed beforefieldinit test.Programm
extends [mscorlib]System.Object
{
// Methods
.method public hidebysig static 
void Main () cil managed 
{
// Method begins at RVA 0x2087
// Code size 31 (0x1f)
.maxstack 8
.entrypoint
IL_0000: nop
IL_0001: ldsfld class test.NameIdObject test.MyCache::MyCacheObject
IL_0006: ldstr "foo"
IL_000b: callvirt instance void test.NameIdObject::set_Name(string)
IL_0010: nop
IL_0011: ldsfld class test.NameIdObject test.MyCache::MyCacheObject
IL_0016: ldc.i4.s 123
IL_0018: callvirt instance void test.NameIdObject::set_Id(int32)
IL_001d: nop
IL_001e: ret
} // end of method Programm::Main
} // end of class test.Programm
}

情况2

.namespace test
{
.class public auto ansi abstract sealed beforefieldinit test.MyCache
extends [mscorlib]System.Object
{
// Fields
.field public static class test.NameIdObject MyCacheObject
} // end of class test.MyCache
.class public auto ansi beforefieldinit test.NameIdObject
extends [mscorlib]System.Object
{
// Fields
.field private string '<Name>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
01 00 00 00 00 00 00 00
)
.field private int32 '<Id>k__BackingField'
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
.custom instance void [mscorlib]System.Diagnostics.DebuggerBrowsableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggerBrowsableState) = (
01 00 00 00 00 00 00 00
)
// Methods
.method public hidebysig specialname 
instance string get_Name () cil managed 
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2050
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld string test.NameIdObject::'<Name>k__BackingField'
IL_0006: ret
} // end of method NameIdObject::get_Name
.method public hidebysig specialname 
instance void set_Name (
string 'value'
) cil managed 
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2058
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld string test.NameIdObject::'<Name>k__BackingField'
IL_0007: ret
} // end of method NameIdObject::set_Name
.method public hidebysig specialname 
instance int32 get_Id () cil managed 
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2061
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld int32 test.NameIdObject::'<Id>k__BackingField'
IL_0006: ret
} // end of method NameIdObject::get_Id
.method public hidebysig specialname 
instance void set_Id (
int32 'value'
) cil managed 
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2069
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stfld int32 test.NameIdObject::'<Id>k__BackingField'
IL_0007: ret
} // end of method NameIdObject::set_Id
.method public hidebysig specialname rtspecialname 
instance void .ctor () cil managed 
{
// Method begins at RVA 0x2072
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method NameIdObject::.ctor
// Properties
.property instance string Name()
{
.get instance string test.NameIdObject::get_Name()
.set instance void test.NameIdObject::set_Name(string)
}
.property instance int32 Id()
{
.get instance int32 test.NameIdObject::get_Id()
.set instance void test.NameIdObject::set_Id(int32)
}
} // end of class test.NameIdObject
.class public auto ansi abstract sealed beforefieldinit test.Program
extends [mscorlib]System.Object
{
// Methods
.method public hidebysig static 
void Main () cil managed 
{
// Method begins at RVA 0x207b
// Code size 33 (0x21)
.maxstack 8
.entrypoint
IL_0000: nop
IL_0001: newobj instance void test.NameIdObject::.ctor()
IL_0006: dup
IL_0007: ldc.i4.s 123
IL_0009: callvirt instance void test.NameIdObject::set_Id(int32)
IL_000e: nop
IL_000f: dup
IL_0010: ldstr "foo"
IL_0015: callvirt instance void test.NameIdObject::set_Name(string)
IL_001a: nop
IL_001b: stsfld class test.NameIdObject test.MyCache::MyCacheObject
IL_0020: ret
} // end of method Program::Main
} // end of class test.Program
}

现在有了这些信息,你就可以分析系统对你的代码做了什么。您可以在案例1中看到,NameIdObject的实例是在MyCache对象的构造函数中创建的。而在情况2中,NameIdObject的实例是在程序的主函数中创建的。

因此,创建对象实例的位置和创建实例的时间是不同的。我希望这有助于决定哪种情况对你的程序最有效。

最新更新