2012-02-29 3 views
2

Я новичок в генериках в C#, и я пытаюсь создать метод, который будет использовать generics. Я попытался создать ключевое слово where при попытке создать локальную переменную, поэтому я уверен, что она будет частью решения.Как я могу сообщить компилятору, что мои дженерики определенно разрешают «| =» или кастинг для int?

Причина в том, что у меня есть несколько различных переменных перечисления, но метод будет делать то же самое с каждым (учитывая строку, которая является одним из определенных значений перечисления, переключает ее, используя перечисление, подобное битовому полю).

У меня есть большая часть этого вместе, часть, которую я сейчас застрял, может рассказать об общем методе, это нормально, чтобы разрешить «| =», так как я уверен, что любой тип, который передается, будет поддерживать оператора.

Я хотел бы иметь возможность поддерживать общность, если это возможно, также может быть перечислением или списком, и я буду выполнять разные коды кода в зависимости от типа.

Пример того, что я везу о

enum someType { value1 = 1<<0, value2 = 1<<1, value3 = 1<<2 }; // and so on 
// some more enums 

private T someMethod<T>(string myIdentifyers) 
    where T: new() 
{ 
    // suppose myIdentifiers is 1 more more of the valid enum options 
    // assume that the correct strings and enum combinations will be passed 
    T retval = new T(); 

    while() { 
    // assume a loop with a method call that parses off one identifyer at a time 
     // if I have to convert the enum to an int first, so be it, but 
     // at this point I can't tell it that a cast to int exists 
     retval |= (T)System.Enum.Parse(typeof(T), oneIdentifyer, false); 
    } 

    return retval; 
} 
+2

Перечисление 'someType' должны быть отмечены с' [Flags] 'атрибут, если вы используете его в качестве набор битфлагов. – asawyer

+0

@asawyer Я просто помещаю [Флаги] перед каждой декларацией перечисления? – Stephen

+0

См. Ответ Бруно Сильвы, он отметил перечисление. – asawyer

ответ

3

Я хотел бы попробовать что-то вроде этого (псевдокод):

[Flags] 
enum someType { value1 = 1<<0, value2 = 1<<1, value3 = 1<<2 }; // and so on 
// some more enums 

private T someMethod<T>(string myIdentifyers) 
    where T: struct, new() 
{ 
      // check if enum 
    if (typeof(T).BaseType != typeof(Enum)) // we should probably check for the flags attribute too 
      throw new Exception(); 

    // suppose myIdentifiers is 1 more more of the valid enum options 
    // assume that the correct strings and enum combinations will be passed 
    int retval = 0; 

    while() { 
    // assume a loop with a method call that parses off one identifyer at a time 
     // if I have to convert the enum to an int first, so be it, but 
     // at this point I can't tell it that a cast to int exists 
     retval |= (int) (object) System.Enum.Parse(typeof(T), oneIdentifyer, false); 
    } 

    return (T) (object) retval; 
} 
+0

Это похоже на работу. – Weeble

+0

До сих пор это работает ... при условии, что я его снова сломаю :-) Для нескольких перечислений я помещаю [Флаги] перед каждым, или это наличие в начале списка объявлений достаточно? – Stephen

+1

Вы должны поместить его перед каждой декларацией перечисления. –

1

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

Смотрите этот же вопрос: Generic C# Code and the Plus Operator

В этом случае, так как вы знаете, ваши перечисления отлитых и из междунар, я думаю, что метод Бруно является путем.

1

Невозможно выразить enum общие ограничения с C# 4. Также невозможно выразить ограничения оператора.

То есть, я думаю, что вы ищете метод, как это:

public static T AssembleFlagsEnum<T>(IEnumerable<string> names) where T : struct 
{ 
    return (T)(object)names.Aggregate(0, 
     (valSoFar, name) => valSoFar | Convert.ToInt32(Enum.Parse(typeof(T), name))); 
} 

Обратите внимание, что это не подтверждает, что данный тип является [Flags] перечисление. Он также не будет работать для перечислений, которые имеют базовые типы, отличные от int.

0

К сожалению, это не возможно.

Ограничить ограничение struct, чтобы указать тип значения, но, очевидно, он содержит больше целых чисел. Единственное, что вы могли бы сделать, это запустить код, чтобы проверить фактический тип.

Поддерживаемые ограничения ограничений описаны в http://msdn.microsoft.com/en-us/library/d5x73970.aspx

Вы не можете сделать оператор ограничения - см Solution for overloaded operator constraint in .NET generics

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