2014-10-03 2 views
2

Я хочу, чтобы строка была децимальной ?. Со ссылкой на предыдущий вопрос hereВставить строку в десятичную? (с нулевым числом) по методу расширения

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

public static class ObjectExtensions 
{ 
    public static Nullable<T> ToNullable<T>(this object input) 
     where T : struct 
    { 
     if (input == null) 
      return null; 
     if (input is Nullable<T> || input is T) 
      return (Nullable<T>)input; 
     throw new InvalidCastException(); 
    } 
} 

использование:

object value = 123.45m; 
decimal? dec = value.ToNullable<decimal>(); 

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

определенно нравится то, что я хотел бы быть в состоянии сделать это: -

object v1 = 123.45m; 
decimal? d1 = v1.ToNullable<decimal>(); 

object v2 = "123.45"; 
decimal? d2 = v2.ToNullable<decimal>(); 
+3

Что это значит, что он не работает со строкой? , строка является ссылочным типом, она не является структурой. – Habib

+0

Я думаю, может быть, они хотят передать строку в качестве ввода и вывести ее «decimal»? Итак: 'string value =" 123.45 "; десятичная дробь? dec = value.ToNullable (); '? EDIT: Конечно, если это так, на данный момент вы не можете просто бросить. Вам нужно будет вызывать 'Decimal.Parse' или некоторый эквивалент для преобразования. –

+0

Лучше использовать Decimal.Parse или Decimal.TryParse для синтаксического анализа строки. Таким образом, любой, кто читает ваш код, точно знает, какие стили культуры и числа вы хотите принять, не обращая внимания на собственный метод расширения. – Joe

ответ

2

Учитывая ваши функции расширения, то почему бы не что-то вроде:

public static class ObjectExtensions 
    { 
     public static Nullable<T> ToNullable<T>(this object input) 
      where T : struct 
     { 
      if (input == null) 
       return null; 
      if (input is Nullable<T> || input is T) 
       return (Nullable<T>)input; 
      else if (input is string) 
       return (T)Convert.ChangeType(input, typeof(T)); 

      throw new InvalidCastException(); 
     } 
    } 

Он будет работать с числовыми типами (поддерживается ChangeType) и даже с датами и так далее.

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

Чтобы улучшить это, вы могли бы перейти к «ChangeType» (в третьем параметре) культуральную вы хотите работать, например return ((T)Convert.ChangeType(input, typeof(T), new CultureInfo("en-US")));

Вы также можете добавить материал в этом методе для обработки исключений и т.д.

+0

отлично, спасибо большое. был смущен структурой Т:. я думал, что не могу передать строку. – mfc

+0

@mfc Я редактировал свой пост с несколькими указаниями о культуре. О вашем замечании, обратите внимание, что «T: struct» относится к выводу, поэтому он не имеет ничего общего с входом, который является «объектом». – AFract

2

Вы могли бы сделать что-то вроде этого:

string nds = null; 
decimal? d = (nds != null) ? Convert.ToDecimal(nds) : default(decimal?); 
+0

нормально, но как определить общую часть метода расширения? Я думал, что можно определить общий общий метод, а затем специально типизированные общие методы для обработки определенных типов? – mfc

+0

Метод, который вы предоставили, обрабатывает их «в общем», просто выполняя приведение типов или распаковку.Это действительно не преобразование между типами. Это просто распаковка десятичной дроби. То, о чем вы просите сейчас, состоит в том, чтобы преобразовать/проанализировать строку в любое произвольное значение типа type_ или, как минимум, различные типы числовых значений. Вы можете создать метод, который проверяет различные сценарии использования, но в противном случае по умолчанию используется 'Convert.ChangeType (input, typeof (T)) и надеюсь, что вы поставили два совместимых типа. –

3

Простой метод расширения преобразует строку в десятичную. Для не пустых строк конечно

public static class StringExtensions 
{ 
    public static decimal? ToNullableDecimal(this string s) 
    { 
     decimal value; 
     if (!Decimal.TryParse(s, out value) 
     return null; 
     return value; 
    } 
} 
0

Вот что работа для меня

1- Создать следующий метод внутри класса (например ValidationHelper)

 public static decimal? Todecimal(string s,decimal defValue=0) 
    { 
     if (s.Trim()!="") 
     { 
      return Convert.ToDecimal(s); 
     } 
     else 
     { 
      return defValue; 
     } 
    } 

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

prod.Qty = ValidationHelper.Todecimal(txtQty.Text,1);//ex: assuming the default value for Qty is 1. 

Надеюсь, это поможет кому-то. Спасибо