общий метод для проверки int, double. Как использовать GetType()?

Я пытаюсь написать метод проверки. Например: для двойного это выглядит так:

   protected bool ValidateLoopAttributes(string i_value, double i_threshold)
       {
        double result;
        if (!(double.TryParse(i_value, out result) && result >= i_threshold))
        {
            return false;
        }
        return true;
    }

Можно ли это записать так:

     protected bool ValidateLoopAttributes<T>(string i_value, T i_threshold)

а затем используйте что-то вроде

             T.GetType().TryParse() // how can i use here the type's methods??

Является ли использование оператора switch/if единственным способом сделать это? Например:

    If (T.GetType() is int) 
        Int32.TryParse(i_threshold)

Есть ли более элегантный способ?


person Dan Dinu    schedule 13.04.2012    source источник
comment
Проверьте ответ Марка Гравелла в этом сообщении: stackoverflow.com/questions/1654871/   -  person Marco    schedule 13.04.2012
comment
GetType() — это метод экземпляра, поэтому T.GetType() не должен даже компилироваться. Вам нужно использовать typeof(T).   -  person Cristian Lupascu    schedule 13.04.2012
comment
Зачем идти на все эти проблемы? Если вас беспокоят только числа с плавающей запятой и целые числа, почему бы просто не использовать две перегрузки, ValidateLoopAttributes(string i_value, double i_threshold) и ValidateLoopAttributes(string i_value, int i_threshold) (или long)?   -  person Rawling    schedule 13.04.2012


Ответы (4)


Попробуй это:

static class Ext
{
    public static bool TryParse<T>(string s, out T value)
    {
        TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
        try
        {
            value = (T)converter.ConvertFromString(s);
            return true;
        }
        catch
        {
            value = default(T);
            return false;
        }
    }
    public static bool ValidateLoopAttributes<T>(string i_value, T i_threshold) 
           where T : IComparable
    {
        T outval;
        if (TryParse<T>(i_value, out outval))
            return outval.CompareTo(i_threshold) >= 0;
        else return false;
    }
}

В моем ответе используется ответ Марка Гравелла, взятый из здесь.
С этим вы можете сделать

bool b1 = Ext.ValidateLoopAttributes<int>("5", 4);
bool b2 = Ext.ValidateLoopAttributes<double>("5.4", 5.5d);

Если вы найдете это полезным, вы также можете использовать метод расширения

public static bool ValidateLoopAttributes<T>(this string i_value, T i_threshold) 
       where T : IComparable { }

что приводит вас к использованию

bool b1 = "5".ValidateLoopAttributes<int>(4);
bool b2 = "5.4".ValidateLoopAttributes<double>(5.5d);
person Marco    schedule 13.04.2012

В настоящее время вы смешиваете две вещи внутри своего метода - синтаксический анализ и бизнес-правила. Представьте, что вы вызываете ValidateLoopAttributes(value, 4), и он возвращает false. Возможные причины:

  1. Строка не содержит значения. Например. пусто, какие-то символы и т.д.
  2. Строка не содержит целочисленного значения. Например. имеет двойную ценность.
  3. Строка содержит целочисленное значение, но оно превышает пороговое значение.
  4. Для вашего типа не определены преобразователи.

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

Итак, подумайте о разделении бизнес-правил и парсинга данных.

Foo foo = Parse(xml);
RunBusinessRules(foo); 
person Sergey Berezovskiy    schedule 13.04.2012

public static bool ValidateLoopAttributes<T>(string value, T threshold)
    where T : IComparable
{
    try
    {
        var parseMethod = typeof(T).GetMethod("Parse", new[] {typeof (string)});
        var result = (T) parseMethod.Invoke(null, new object[] {value});
        return result.CompareTo(threshold) < 0;
    }
    catch (Exception)
    {
        return false;
    }
}

Очевидно, это работает только для типов со статическим методом Parse.

person Scroog1    schedule 13.04.2012

Можно попробовать использовать что-то вроде этого, чтобы проверить, является ли это целым числом или нет:

public static bool IsNumericValue(string val, System.Globalization.NumberStyles NumberStyle)
{
    double result;
    return Double.TryParse(val,NumberStyle,
        System.Globalization.CultureInfo.CurrentCulture,out result);
}

so on

 IsNumericValue("1.2", System.Globalization.NumberStyles.Integer) // FALSE 

и дальше

 IsNumericValue("12", System.Globalization.NumberStyles.Integer)  // TRUE

Обратите внимание, что в этом примере я использовал CurrectCulture, подгоните под ваши потребности, если они отличаются.

person Tigran    schedule 13.04.2012