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

时间:2009-12-31 01:33:28

标签: 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;
        }
    }

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

3 个答案:

答案 0 :(得分: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

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

答案 1 :(得分:8)

这将以线程安全的方式为每个Type创建一个唯一的整数标识符,具体取决于它所访问的顺序。

例如,如果你这样做:

int myClassId = Ident.TypeIndex<MyClass>();
int mySecondClssId = Ident.TypeIndex<MySecondClass>();

你将获得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>());

它将打印:

0
1
0
1

但是,使用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;
    }
} 

答案 2 :(得分:2)

它返回调用Ident.TypeIndex的次数,可能是为每个对象分配一个唯一的编号。

由于他们使用泛型的方式,每种类型T都应该有不同的数字序列。所以你可以有一个#1圆,一个#2圆和一个#1方。