以下C#代码有什么作用?

zfe*_*ran 4 c# generics

我在C#XNA图形api中遇到了以下类,我不确定它是做什么的,或者它需要如此模糊.(T被约束为父类中的结构)

    static class Ident
    {
        static object sync = new object();
        static volatile int index = 0;
        static int Index
        {
            get
            {
                lock (sync)
                    return index++;
            }
        }
        class Type<T>
        {
            public static int id = Index;
        }
        public static int TypeIndex<T>()
        {
            return Type<T>.id;
        }
    }
Run Code Online (Sandbox Code Playgroud)

API仅在调用此静态类时生成: int index = Ident.TypeIndex<T>();

Dia*_*tis 8

它为每个不同类型T分配应用程序范围(静态)和线程安全(锁定同步对象+易失性索引)唯一标识符.

例如:

Console.WriteLine(Ident.TypeIndex<int>()); // 0
Console.WriteLine(Ident.TypeIndex<string>()); // 1
Console.WriteLine(Ident.TypeIndex<long>()); // 2
Console.WriteLine(Ident.TypeIndex<int>()); // 0
Run Code Online (Sandbox Code Playgroud)

Volatile用于确保当前线程不会缓存索引值,并且锁定会阻止多个线程访问它.

  • +1提及线程影响. (3认同)

Ree*_*sey 8

这将以线程安全的方式基于每个类型访问的顺序为每个类型创建唯一的整数标识符.

例如,如果你这样做:

int myClassId = Ident.TypeIndex<MyClass>();
int mySecondClssId = Ident.TypeIndex<MySecondClass>();
Run Code Online (Sandbox Code Playgroud)

您将得到2个"TypeIndex"数字(mySecondClassId至少比myClassId多1个,但由于线程可能更大).稍后,如果再次使用同一个类调用它,它将返回该类的相同TypeIndex.

例如,如果我运行它,使用:

Console.WriteLine(Ident.TypeIndex<Program>());
Console.WriteLine(Ident.TypeIndex<Test>());
Console.WriteLine(Ident.TypeIndex<Program>());
Console.WriteLine(Ident.TypeIndex<Test>());
Run Code Online (Sandbox Code Playgroud)

它将打印:

0
1
0
1
Run Code Online (Sandbox Code Playgroud)

但是,使用Interlocked.Increment可以更有效地完成此操作,这将完全避免锁和同步对象的需要.以下给出了完全相同的答案,不需要锁定:

static class Ident
{
    static int index = -1;
    static int Index
    {
        get
        {

            return Interlocked.Increment(ref index);
        }
    }
    private static class Type<T>
    {
        public static int id = Index;
    }

    public static int TypeIndex<T>()
    {
        return Type<T>.id;
    }
} 
Run Code Online (Sandbox Code Playgroud)