2012-01-04 5 views
2

Прямо к коду:Использование метода парсера с общим типом?

class ArithmeticExpressionParser<T> : Parser 
{ 
    T num1, num2; 

    /* ......... */ 

    void ParseNumber() 
    { 
     string temp = String.Empty; 

     while (char.IsDigit(PeekNextToken())) 
     { 
      GetNextToken(); 
      temp += Token; 
     } 

     num1 = T.Parse(temp); // <<< the problem 
    } 

В принципе, если бы я был используя int или double я бы просто использовать int.Parse и т.д. Я попытался литья num1 = (T)temp;, который не работал. Как я могу это сделать без необходимости писать пользовательскую функцию string до T?

+1

Он чувствует, как вы хотите '' IParsable' но IConvertible' является более широким (и существует) – Jodrell

ответ

9
class ArithmeticExpressionParser<T> : Parser where T : IConvertible 
{ 
    T num1, num2; 

    /* ......... */ 

    void ParseNumber() 
    { 
     string temp = String.Empty; 

     while (char.IsDigit(PeekNextToken())) 
     { 
      GetNextToken(); 
      temp += Token; 
     } 

     //num1 = T.Parse(temp); // <<< the problem 
     num1 = (T)Convert.ChangeType(temp, typeof(T)); 
    } 
} 

Это предполагает, что все типов вы превращающие реализацию IConvertible, что позволит вам разместить общие ограничения на классе парсера. Если не все типы являются конвертируемыми, вам нужно будет переключить методы преобразования на основе типа (беспорядочно).

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

http://msdn.microsoft.com/en-us/library/system.iconvertible.aspx

+0

Используя Convert.ChangeType, у вас есть бокс, когда T - тип значения. – phoog

3

Используйте Convert.ChangeType для преобразования. Следующий код должен работать со всеми типами простых и

public static T Parse<T>(this string source) 
    {    
     if (typeof(T).IsSubclassOf(typeof(Enum))) 
     { 
      return (T)Enum.Parse(typeof(T), source, true); 
     } 

     if (!String.IsNullOrEmpty(source)) 
      return (T)Convert.ChangeType(source, typeof(T)); 

     return default(T); 
    } 
+0

Convert.ChangeType вызывает бокс, однако, что можно было бы избежать, используя группу методов перегрузкам. – phoog

+0

@phoog - перегрузки методов в этом случае не работают, поскольку различие в типе относится к типу возврата, а не к типу параметра - параметр всегда является строкой, поэтому перегрузка не применима. –

+0

@DaveRael хорошая точка, я использовал неправильное слово. То, что я хотел указать, - это группа методов, которые включают имя типа в имени метода, например, в 'X.ParseDouble' и' X.ParseByte', который больше не печатает, чем 'X.Parse ' и ' X.Parse '. – phoog

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