是否存在使用未引用对象进行垃圾收集的风险

时间:2021-07-28 23:58:11

Sometimes I dont want to write a new line to declare a Regex object so I write the following code

有时我不想写一个新行来声明一个Regex对象,所以我写下面的代码

MatchCollection matchCollection = new Regex("example").Matches(someText);

With my limited knowledge, I think new Regex("example") might be garbage collected before the Matches start but it is nearly not possible as the operation is so fast.

由于我的知识有限,我认为新的正则表达式(“示例”)可能在匹配开始之前被垃圾收集,但由于操作速度太快,几乎不可能。

Am I wrong? Is this kind of coding a bad practice that I should avoid?

我错了吗?这种编码是一种我应该避免的不良做法吗?

1 个解决方案

#1


3  

No. It is not possible that the object gets GC'ed before it is actually used.

不可以。对象在实际使用之前不可能得到GC。

In fact it is (almost) the same as:

实际上它(几乎)与以下相同:

var r = new Regex("example");
MatchCollection matchCollection = r.Matches(someText);

As a proof: here is the IL from an console application containing the code above (1), and a oneliner (2):

作为证明:这是来自包含上面代码(1)的控制台应用程序的IL和oneliner(2):

Seperate variables:

单独的变量:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       27 (0x1b)
  .maxstack  2
  .locals init ([0] string someText,
           [1] class [System]System.Text.RegularExpressions.Regex r,
           [2] class [System]System.Text.RegularExpressions.MatchCollection matchCollection)
  IL_0000:  nop
  IL_0001:  ldstr      "s"
  IL_0006:  stloc.0
  IL_0007:  ldstr      "example"
  IL_000c:  newobj     instance void [System]System.Text.RegularExpressions.Regex::.ctor(string)
  IL_0011:  stloc.1
  IL_0012:  ldloc.1
  IL_0013:  ldloc.0
  IL_0014:  callvirt   instance class [System]System.Text.RegularExpressions.MatchCollection [System]System.Text.RegularExpressions.Regex::Matches(string)
  IL_0019:  stloc.2
  IL_001a:  ret
} // end of method Program::Main

Oneliner:

Oneliner:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       25 (0x19)
  .maxstack  2
  .locals init ([0] string someText,
           [1] class [System]System.Text.RegularExpressions.MatchCollection matchCollection)
  IL_0000:  nop
  IL_0001:  ldstr      "s"
  IL_0006:  stloc.0
  IL_0007:  ldstr      "example"
  IL_000c:  newobj     instance void [System]System.Text.RegularExpressions.Regex::.ctor(string)
  IL_0011:  ldloc.0
  IL_0012:  call       instance class [System]System.Text.RegularExpressions.MatchCollection [System]System.Text.RegularExpressions.Regex::Matches(string)
  IL_0017:  stloc.1
  IL_0018:  ret
} // end of method Program::Main

You will see that the actual code is not the same. The pushes and pops one variable more from the stack, and the actual call is a little different, but that's all there is. They still call the same object, only the place where it exists is different.

您将看到实际代码不一样。从堆栈中推送和弹出一个变量,实际调用有点不同,但这就是全部。它们仍然调用相同的对象,只有它存在的地方是不同的。

#1


3  

No. It is not possible that the object gets GC'ed before it is actually used.

不可以。对象在实际使用之前不可能得到GC。

In fact it is (almost) the same as:

实际上它(几乎)与以下相同:

var r = new Regex("example");
MatchCollection matchCollection = r.Matches(someText);

As a proof: here is the IL from an console application containing the code above (1), and a oneliner (2):

作为证明:这是来自包含上面代码(1)的控制台应用程序的IL和oneliner(2):

Seperate variables:

单独的变量:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       27 (0x1b)
  .maxstack  2
  .locals init ([0] string someText,
           [1] class [System]System.Text.RegularExpressions.Regex r,
           [2] class [System]System.Text.RegularExpressions.MatchCollection matchCollection)
  IL_0000:  nop
  IL_0001:  ldstr      "s"
  IL_0006:  stloc.0
  IL_0007:  ldstr      "example"
  IL_000c:  newobj     instance void [System]System.Text.RegularExpressions.Regex::.ctor(string)
  IL_0011:  stloc.1
  IL_0012:  ldloc.1
  IL_0013:  ldloc.0
  IL_0014:  callvirt   instance class [System]System.Text.RegularExpressions.MatchCollection [System]System.Text.RegularExpressions.Regex::Matches(string)
  IL_0019:  stloc.2
  IL_001a:  ret
} // end of method Program::Main

Oneliner:

Oneliner:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       25 (0x19)
  .maxstack  2
  .locals init ([0] string someText,
           [1] class [System]System.Text.RegularExpressions.MatchCollection matchCollection)
  IL_0000:  nop
  IL_0001:  ldstr      "s"
  IL_0006:  stloc.0
  IL_0007:  ldstr      "example"
  IL_000c:  newobj     instance void [System]System.Text.RegularExpressions.Regex::.ctor(string)
  IL_0011:  ldloc.0
  IL_0012:  call       instance class [System]System.Text.RegularExpressions.MatchCollection [System]System.Text.RegularExpressions.Regex::Matches(string)
  IL_0017:  stloc.1
  IL_0018:  ret
} // end of method Program::Main

You will see that the actual code is not the same. The pushes and pops one variable more from the stack, and the actual call is a little different, but that's all there is. They still call the same object, only the place where it exists is different.

您将看到实际代码不一样。从堆栈中推送和弹出一个变量,实际调用有点不同,但这就是全部。它们仍然调用相同的对象,只有它存在的地方是不同的。