2013-05-31 2 views
6

Я написал перегружен статическими TryParse методов для следующих типов Nullable: int?, short?, long?, double?, DateTime?, decimal?, float?, bool?, byte? и char?. Ниже приведены некоторые из них:типов TryParse Обнуляемых обобщенно

protected static bool TryParse(string input, out int? value) 
{ 
    int outValue; 
    bool result = Int32.TryParse(input, out outValue); 
    value = outValue; 
    return result; 
} 

protected static bool TryParse(string input, out short? value) 
{ 
    short outValue; 
    bool result = Int16.TryParse(input, out outValue); 
    value = outValue; 
    return result; 
} 

protected static bool TryParse(string input, out long? value) 
{ 
    long outValue; 
    bool result = Int64.TryParse(input, out outValue); 
    value = outValue; 
    return result; 
} 

Логика одинакова во всех методах, за исключением того, что они используют разные типы. Невозможно было бы использовать дженерики, чтобы мне не было так много избыточного кода? Подпись будет выглядеть следующим образом:

bool TryParse<T>(string input, out T value); 

Благодаря

+1

Одна из причин, общий метод для этого не подходит не все '' struct's имеют методы TryParse', но вы не можете использовать общие ограничения, чтобы только совместимых типов во время компиляции. – Sam

+0

Кстати, вам не хватает '?' После второго 'T' в предложенной вами сигнатуре метода. – Sam

ответ

9

не было бы возможно использовать дженерики, так что мне не нужно иметь так много лишнего кода?

Вы можете сделать это с отражением, но это будет относительно медленно. В противном случае вы получите . Создайте карту от типа к «методу для использования для этого типа», но это будет довольно уродливо. Помимо всего прочего, он никогда не будет действительно generic - он будет работать только для типов, которые предоставили метод правильной подписи TryParse, который не мог быть известен во время компиляции.

Я бы лично подумал об изменении подписи и поведения, между прочим. В настоящее время, хотя тип value является нулевым, он никогда не будет иметь нулевого значения в конце метода, даже если вы вернете false. Почему бы не сделать возвращаемое значение результатом операции синтаксического анализа, вернув null при ошибке?

protected static long? TryParseInt64(string input) 
{ 
    long outValue; 
    return Int64.TryParse(input, out outValue) ? (long?) outValue : null; 
} 
+0

В таком случае я буду держаться подальше от дженериков. Что касается вашего предложения, мне нужно, чтобы подпись была в форме 'bool TryParse (string input, out object value)', чтобы она соответствовала методам .NET TryParse. – davenewza

+0

@davenewza: Тогда вы должны * хотя бы * изменить поведение так, чтобы 'value' был' null', если 'result' является' false', чтобы соответствовать другим методам TryParse: параметр 'out' должен всегда имеют значение по умолчанию типа (которое является «null» для типов с нулевым значением), когда оно возвращает «false». –

+0

Ах, абсолютно. Спасибо что подметил это. – davenewza

4

Как и в сторону, вы могли бы реорганизовать код:

public static bool TryParse(string input, out int? value) 
{ 
    return TryParse(input, Int32.TryParse, out value); 
} 

protected static bool TryParse(string input, out short? value) 
{ 
    return TryParse(input, Int16.TryParse, out value); 
} 

protected static bool TryParse(string input, out long? value) 
{ 
    return TryParse(input, Int64.TryParse, out value); 
} 

private static bool TryParse<T>(string input, TryParseFunc<T> tryParse, out T? value) 
    where T : struct 
{ 
    T outValue; 
    bool result = tryParse(input, out outValue); 
    value = outValue; 
    return result; 
} 

private delegate bool TryParseFunc<T>(string input, out T value); 
+3

Мне это нравится. Это аккуратно. Это также делает изменение, которое я предлагаю очень просто - вы просто используете 'value = result? outValue: (T?) null' на третьей строке части реализации. –

+0

Это замечательно. Благодаря! Будет также включать значение «null» по умолчанию, предложенное Джоном. – davenewza

+1

Должен быть значок для отправки ответа, который @JonSkeet сам одобряет в комментарии. –

5

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

public static Nullable<TSource> TryParse<TSource>(this string input) where TSource : struct 
{ 
    try 
    { 
     var result = Convert.ChangeType(input, typeof(TSource)); 
     if (result != null) 
     { 
      return (TSource)result; 
     } 
     return null; 
    } 
    catch (Exception) 
    { 
     return null; 
    } 
} 

Следующий вызов возвращает обнуляемого разобранный вид.

string s = "510"; 
int? test = s.TryParse<int>(); 
//TryParse Returns 510 and stored in variable test. 

string s = "TestInt"; 
int? test = s.TryParse<int>(); 
//TryParse Returns null and stored in variable test. 
Смежные вопросы