Общий синтаксический анализатор строк - PullRequest
1 голос
/ 17 июня 2011

Мне нужен универсальный метод, который может возвращать значение, проанализированное из строки

public T GetDefaultValue<T>(){
    // if typeof(T) is Double it should try to parse some string (supposedly which's been read from DB), 
    // and return Double value, or if typeof(T) is Int, then it should parse the string 
    //into Int, and finally if typeof(T) is a string, then no parsing is needed.
}

UPD ... Почему я не могу проверить, является ли T некоторый определенный тип, и использоватьРазбирать метод соответственно?

Ответы [ 5 ]

2 голосов
/ 17 июня 2011

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

public T Parse<T>(string input)
{
     return (T)Convert.ChangeType(input, typeof(T));
}

int x = Parse<int>("1");
double y = Parse<double>("1.0");
string z = Parse<string>("hey");

Обратите внимание, что даже для того, чтобы сделать эту работу, вы указываете свои типы? Какая экономия по сравнению с использованием int.Parse (или TryParse), double.Parse и т. Д .?

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

int x = myDataRow.Field<int>("Column1"); // or
int x = (int)myDataRow["Column1"];

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

int? x = myDataRow.Field<int?>("Column1"); // or
int x = myDataRow.Field<int?>("Column1").GetValueOrDefault(); // normalize nulls to 0
1 голос
/ 17 июня 2011

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

Я тоже не понимаю, почему ваша функция называется GetDefaultValue. Почему бы не Parse, TryParse, ConvertFromString или что-то в этом роде? Когда я вижу функцию с именем GetDefaultValue, я не думаю о функции синтаксического анализа.

Проверьте этот старый вопрос: Можно ли создать общий синтаксический анализатор чисел в C #? , который имеет несколько соответствующих ответов.


И мой старый ответ оттуда:

Я написал некоторый код, который использует отражение, чтобы найти Parse / TryParse методы для типа и получить доступ к ним из универсальных функций:

private static class ParseDelegateStore<T>
{
    public static ParseDelegate<T> Parse;
    public static TryParseDelegate<T> TryParse;
}

private delegate T ParseDelegate<T>(string s);
private delegate bool TryParseDelegate<T>(string s, out T result);


public static T Parse<T>(string s)
{
    ParseDelegate<T> parse = ParseDelegateStore<T>.Parse;
    if (parse == null)
    {
        parse = (ParseDelegate<T>)Delegate.CreateDelegate(typeof(ParseDelegate<T>), typeof(T), "Parse", true);
        ParseDelegateStore<T>.Parse = parse;
    }
    return parse(s);
}

public static bool TryParse<T>(string s, out T result)
{
    TryParseDelegate<T> tryParse = ParseDelegateStore<T>.TryParse;
    if (tryParse == null)
    {
        tryParse = (TryParseDelegate<T>)Delegate.CreateDelegate(typeof(TryParseDelegate<T>), typeof(T), "TryParse", true);
            ParseDelegateStore<T>.TryParse = tryParse;
    }
    return tryParse(s, out result);
}

https://github.com/CodesInChaos/ChaosUtil/blob/master/Chaos.Util/Conversion.cs

Но я не слишком много их тестировал, так что они могут иметь некоторые ошибки / работать некорректно с каждым типом. Обработка ошибок тоже немного отсутствует.

И у них нет перегрузок при разборе инварианта культуры. Поэтому вам, вероятно, нужно добавить это.

1 голос
/ 17 июня 2011

Вы можете сделать что-то подобное без генериков. Зачем использовать меч, когда все, что вам нужно, это игла

class Test
    {
        public string ReadFromDb()
        {
            //Do your db work here
            return "";
        }

        public bool GetDefaultValue(ref int t1)
        {
            t1 = Int32.Parse(ReadFromDb());
            return true;
        }

        public bool GetDefaultValue(ref double t1)
        {
            t1 = Double.Parse( ReadFromDb() );
            return true;
        }

        public bool GetDefaultValue(ref string t1)
        {
            t1 = ReadFromDb();
            return true;
        }
    }
1 голос
/ 17 июня 2011

Я бы просто сделал строковые расширения, такие как

public static int xToInt(this string source, int alternate = 0)
{
   int result;
   return (int.TryParse(source, out result) ? result : alternate);
}

И затем просто создал бы одно для Double, и вы могли бы затем использовать его, выполнив

int someNumber  = "123456".xToInt();
int someNumber2 = "omg!".xToInt(333);
1 голос
/ 17 июня 2011

Какой смысл использовать дженерики для этого?Вы теряете все преимущества дженериков, проверяя фактические типы.

Просто есть три перегрузки, одна для int, одна для double и (вероятно, ненужная) string.

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