2009-12-31 2 views
4

Я наткнулся на следующий класс в графике api C# XNA, и я не уверен, что он делает или что он должен быть настолько неясным. (Т ограничена, чтобы быть структура в родительский класс)Что делает следующий код C#?

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>();

ответ

8

Это создает уникальный целочисленный идентификатор для каждого Типа, основанный на порядке, к которому он обращается, в потокобезопасном режиме.

Например, если вы:

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

Вы получите 2 "TypeIndex" номера (с mySecondClassId, по меньшей мере 1 больше, чем myClassId, но потенциально больше, из-за многопоточности). Позже, если вы вызовете это снова с тем же классом, он вернет тот же 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; 
    } 
} 
+1

+1 для лучшей альтернативы – Diadistis

+1

Любопытный - почему downvoting? –

+0

Спекуляция - Незнание – Diadistis

2

Это возвращает число раз Ident.TypeIndex был вызван, вероятно, присваивать уникальный номер каждому объекту.

Из-за того, как они используют дженерики, для каждого типа T должна быть другая последовательность чисел. Таким образом, вы можете иметь круг № 1, круг № 2 и квадрат # 1.

+0

Nice ... код может использовать некоторые комментарии наверняка. –

+3

На самом деле - это неправда. Вы получаете уникальный int для каждого типа, потому что каждый тип использует один статический идентификатор. Вы не получите новую последовательность для каждого типа. –

+3

Если вы это назовете, вы получите 0: Круг, 0: Круг, 1: Квадрат, 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 

Летучие который используется чтобы текущий поток не кэшировал значение индекса, и блокировка предотвращает доступ к нему более чем одного потока.

+3

+1 для упоминания о потолочных импликации. –

Смежные вопросы