Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .Net Framework 4.0-字典中存在带int键的操作码.Box_C#_.net_Dictionary_Garbage_Xbox360 - Fatal编程技术网

C# .Net Framework 4.0-字典中存在带int键的操作码.Box

C# .Net Framework 4.0-字典中存在带int键的操作码.Box,c#,.net,dictionary,garbage,xbox360,C#,.net,Dictionary,Garbage,Xbox360,我正试图调查在较新版本的.Net(比如>=4)中,带有枚举键的字典是否仍会生成垃圾 请参阅Shawn Hargreaves的博客文章,了解我为什么对此感到烦恼的详细信息。。。 () 我知道非常具体,但xbox上的垃圾是/可能是一个非常严重的问题 我创建了一个小小的.NETV4控制台应用程序,比较Dictionary和Dicationary生成的IL,发现两组代码中都有一个“box”操作码,这让我很困惑 .method private hidebysig instance int32 F

我正试图调查在较新版本的.Net(比如>=4)中,带有枚举键的字典是否仍会生成垃圾

请参阅Shawn Hargreaves的博客文章,了解我为什么对此感到烦恼的详细信息。。。 () 我知道非常具体,但xbox上的垃圾是/可能是一个非常严重的问题

我创建了一个小小的.NETV4控制台应用程序,比较Dictionary和Dicationary生成的IL,发现两组代码中都有一个“box”操作码,这让我很困惑

.method private hidebysig 
    instance int32 FindEntry (
        !TKey key
    ) cil managed 
{
    // Method begins at RVA 0x61030
    // Code size 138 (0x8a)
    .maxstack 3
    .locals init (
        [0] int32,
        [1] int32
    )

    IL_0000: ldarg.1
    IL_0001: box !TKey   <----Hmmmm!
    IL_0006: brtrue.s IL_000e

    IL_0008: ldc.i4.5
    IL_0009: call void System.ThrowHelper::ThrowArgumentNullException(valuetype System.ExceptionArgument)

    IL_000e: ldarg.0
    IL_000f: ldfld int32[] class System.Collections.Generic.Dictionary`2<!TKey, !TValue>::buckets
    IL_0014: brfalse.s IL_0088
.method私有隐藏
实例int32 FindEntry(
!TKey键
)cil管理
{
//方法从RVA 0x61030开始
//代码大小138(0x8a)
.maxstack 3
.init(
[0]int32,
[1] int32
)
IL_0000:ldarg.1
IL_0001:box!TKey

将值类型(valTypeToken中指定的类型)转换为true 对象引用

这里的框不是堆分配吗?如果不是,那么我如何判断何时存在可能导致Xbox陷入困境的堆分配?(从IL看)它是否依赖于其他上下文?
内存探查器(例如CLR探查器)是唯一确定的方法吗?

是的,它是一个框,但在这种情况下不应该重要-至少,对于常规的.NET不是这样;这是一个
!=null
检查;JIT知道如何识别这些值类型,并且可以从机器代码中删除该检查

据说

要确定这一点,您需要查看post JIT机器代码,而不是IL

使用哪种JIT也很重要,这会使它变得更难


最坏的情况:您可以使用CoreCLR代码来滚动您自己的值类型字典。

我会说问题已经解决了。我从

然后我得到了许多
TestEnum
的分配

其他测试:

public class TestEnumComparer : IEqualityComparer<TestEnum>
{

    public bool Equals(TestEnum x, TestEnum y)
    {
        return x == y;
    }

    public int GetHashCode(TestEnum obj)
    {
        return obj.GetHashCode();
    }
}
有一些特殊的代码可以比较
int
enum
,并且只有它们

如果我将
enum
更改为

enum TestEnum : long
然后出现由装箱引起的分配!:-)

那么最后呢,

Dictionary<enum_that_is_an_int, Foo>
字典
是否安全使用

其他每种类型的
enum
都不是


请注意,对于.NET>=4.0,这是正确的。我已经查看了mscorlib 2.0.0.0的
CreateComparer()
,没有这样的检查,因此.NET 2.0-3.5的
字典使用起来不安全。

您发布的链接(在其中一条注释中)另一个链接:这是关于枚举装箱的问题啊,很高兴知道-谢谢-至少对于桌面CLR无论如何-Xbox上的CF可能会做一些不同的事情,我想(就像Mono一样)-使用内存分析器检查似乎是唯一可以确定的方法。@PaulCunningham或者你可以在有点偏执的情况下快乐地生活,并实现一个执行强制转换的
IEqualityComparer
。与此同时,所有可能的底层类型都没有了这个好的ol'装箱问题:
Dictionary<TestEnum, int> dict = new Dictionary<TestEnum, int>(new TestEnumComparer());
// If T is an int-based Enum, return an EnumEqualityComparer<T>
// See the METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST and METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST_LONG cases in getILIntrinsicImplementation
if (t.IsEnum && Enum.GetUnderlyingType(t) == typeof(int))
{
    return (EqualityComparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer<int>), t);
}
enum TestEnum : long
Dictionary<enum_that_is_an_int, Foo>