C#: 匿名变量的内存分配

4
我对匿名类型变量的内存分配有疑问。
如果我声明一个变量 int Variable_Name ,它将分配 4个字节
但是在匿名类型的情况下,会发生什么情况?内存何时被释放?
我们需要手动释放吗?
例如, List<String> MyList = new List<String> { "0", "1", "0"}.Where(X => X != "1").ToList(); 这里为X分配了多少字节
2个回答

9

你实际上没有展示任何匿名类型。你展示的是一个Lambda表达式。在这种情况下,编译器会为你创建一个额外的方法,类似于这样:

private static bool SomeUnspeakableName(string X)
{
    return X != "1";
}

那么你的代码将被转换为以下内容:
List<String> MyList=new List<String>{"0","1","0"}
       .Where(new Func<string, bool>(SomeUnspeakableName))
       .ToList();

除了实际上,编译器在这种情况下会创建一个单一的委托实例并缓存它。(当然,它还会将扩展方法的使用转换为对Enumerable.WhereEnumerable.ToList的普通调用。)

因此,X最终成为一个字符串参数。在执行时,没有lambda表达式的概念(暂不考虑表达式树)。只有使用生成的方法创建的委托。

现在,如果您正在使用匿名类型,就像这样:

var anon = new { Name = "Jon", Age = 34 };

那么这只会创建一个新的类,包含一个 string 变量和一个 int 变量,并且与包含一个 string(当然是一个引用)和一个 int 的普通类具有相同的内存占用。


1
@ Jon Skeet:我在询问LAMBDA表达式中的X - Thorin Oakenshield
1
@Pramodh:我已经展示了它的作用。它有效地成为生成方法中的一个参数。 - Jon Skeet
@ Jon Skeet:谢谢你...如果我使用for循环和if条件而不是上述的lambda表达式,哪个会使用更多的内存,lambda还是for - if循环? - Thorin Oakenshield
@Pramodh:考虑到 JIT 实际上发生了什么,很难准确地说 JIT 后会发生什么。但是差异微不足道。你在这里担心了错误的事情 - 让代码尽可能易读。 - Jon Skeet
哈哈,当我看到这个问题时,我立刻想到这是一个Jon Skeet的问题。 - Jaco Pretorius

2
List<String> MyList = new List<String>{"0","1","0"}.Where(X=>X!="1").ToList();

这不是匿名类型。它是一个集合初始化器,创建一个包含3个元素的列表,然后过滤最初创建的列表。

匿名类型的行为和内存消耗与它们的非匿名类型等效物相同。

var foo = new 
{
    Prop1 = "value1",
    Prop2 = "value2"
};

如果我们有一个类型,则与之相同:

class Foo 
{
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
}

...
var foo = new Foo 
{
    Prop1 = "value1",
    Prop2 = "value2"
};

1
@ Darin Dimitrov :X怎么样? - Thorin Oakenshield
@Pramodh x 不是一个变量,而是一个委托。 - RPM1984
2
@RPM1984: 不,X是Lambda表达式中的参数,在生成的方法中最终成为一个参数。 - Jon Skeet
你说得对,我指的是lambda表达式的第一部分(X =>)。我曾经认为lambda表达式是在说“X”是一个委托,其中X!=“1”被处理。 - RPM1984
@RPM1984:不,它是在说X是委托内的一个参数。整个lambda表达式会被转换成委托。请参考我的回答以了解编译器执行的转换过程。 - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接