I am attempting to cast a string gotten from a local database into decimal, but resulted in a "Cannot implicitly convert Type 'GlobalCurrencyConverter.CurrencyRateDataSet.rateDataTable' to decimal".
Below is my code,
protected decimal calRate_Click(object sender, EventArgs e)
{
CurrencyRateDataSetTableAdapters.rateTableAdapter rateTable;
decimal exRate = (decimal)rateTable.GetDataBySourceTargetCurrency(objDropDownSourceCUR.SelectedValue, objDropDownTargetCUR.SelectedValue);
decimal exAmt = 0;
exAmt = (decimal)Convert.ToDecimal(objTextBoxSourceAmt.Text);
}
Update:
rateTable.getDataBySourceTargetCurrency is a method created in Visual Studio Designer. It takes in 2 parameters and search through the local database, returning a single row (and single column) of value.
If "rateTable.GetDataBySourceTargetCurrency(objDropDownSourceCUR.SelectedValue, objDropDownTargetCUR.SelectedValue)" is in fact a string (from your title), try Decimal.TryParse():
//Just noticed questions above... if rateTable.GetDataBy... does not return a string, you must create a string from whatever object it does return, then use TryParse()
Decimal exRate;
String exRateString = rateTable.GetDataBySourceTargetCurrency(objDropDownSourceCUR.SelectedValue, objDropDownTargetCUR.SelectedValue);
bool convertSuccessful = Decimal.TryParse(exRateString, out exRate);
if (convertSuccessful == true)
{
// do some stuff here
}
else
{
// report error
}
Try this:
public static class StringUtils
{
public static string ToCurrency(decimal value)
{
return value.ToString("C");
}
public static decimal FromCurrency(string value)
{
return decimal.Parse(value, NumberStyles.Currency);
}
public static decimal? FromCurrency(string value, decimal? defaultValue)
{
decimal num;
if(decimal.TryParse(value, NumberStyles.Currency, null, out num))
return num;
return defaultValue;
}
}
From which you can do this:
decimal exAmt = StringUtils.FromCurrency(objTextBoxSourceAmt.Text,0);
Related
This is my code to check if the value can be converted to given type.
public static object TryParseObject<T>(object valueObject)
{
string value = null;
try
{
value = Convert.ToString(valueObject);
var converter = TypeDescriptor.GetConverter(typeof(T));
if (converter != null)
{
//Cast ConvertFromString(string text) : object to (T)
return (T)converter.ConvertFromString(value);
}
return default(T);
}
catch
{
//Can't parse
}
}
This works as it should be. Now I need to convert from date string to DateTime with custom format only (say for ex. format: "MM.DD.YYYY HH:mm:ss"). How can I achieve that?
Should I handle the DateTime scenario separately? like:
if(typeof(T) == typeof(DateTime)) {...}
else {...}
I'm looking to see if I can use the existing code with few changes. Thanks.
If you change a method signature to the same as other TryParse.. methods
public static bool TryParseObject<T>(object valueObject, out T outValue)
{
//your parsing code
}
Then you can create overloads for any type you want. With separated method your code stay clean and easy to understand
public static bool TryParseObject(object valueObject, out DateTime outValue)
{
const string EXACT_FORMAT = "MM.DD.YYYY HH:mm:ss";
// your parsing to DateTime
}
public static bool TryParseObject(object valueObject, out int outValue)
{
// your parsing to int
}
I would like this method to be able to handle decimal? also.
Is this possible? I dont want to use object as parameter type.
public static string SurroundWithQuotes(double? amount)
{
if (amount == null)
{
return String.Empty;
}
string format = "{0:0,0.00}";
string formattedNumber = String.Format(format, amount);
if (amount < 1000)
{
return formattedNumber;
}
else
{
string quote = "\"";
return quote + formattedNumber + quote;
}
}
Create another method with the same name, but use a decimal parameter.
public static string SurroundWithQuotes(decimal? amount)
When you call the method with a decimal, it will select the correct one.
This is called overloading.
You can just have your main version of the method accept a decimal? and make a one-line overload for double?:
public static string SurroundWithQuotes(double? amount)
{
return SurroundWithQuotes((decimal?)amount);
}
That will work just fine.
Or you can have a generic method like this:
public static string SurroundWithQuotes<T>(T amount)
{
if (amount == null)
{
return String.Empty;
}
string format = "{0:0,0.00}";
string formattedNumber = String.Format(format, amount);
decimal amnt = Convert.ToDecimal(amount);
if (amnt < 1000)
{
return formattedNumber;
}
else
{
string quote = "\"";
return quote + formattedNumber + quote;
}
}
The constraint is that the type T must be able to be casted to decimal.
I'm searching for a general way to convert strings to a type.
For example:
class SomeThing<T> {
public void Add(T value) {
//...
}
public void Add(string value) {
// Try to convert from string to T ???
}
}
Usage:
SomeThing<double> list = new SomeThing<double>();
list.Add(123.45);
list.Add("234.56");
It should have there features:
- If the type supports convertion from string, convert it.
- If the type does not support convertion from string, either throw exception or return default(T).
- For numbers (double, int) it should use invariant culture.
How can I accomplish this?
You can try doing something like this:
public void AddRange(string value) {
var converter = TypeDescriptor.GetConverter(typeof(T));
if (!Object.Reference(converter, null))
if (converter.CanConvertFrom(typeof(String)) {
T result = (T) converter.ConvertFrom(value);
// value is converted to T; your code here
...
return;
}
// Type T can't be obtained from String directly
// 1. Do it using by-ways (spesific for particular T's)
// 2. Use default(T)
// 3. Throw exception
...
you can try this
class SomeThing<T>
{
public void Add(T value)
{
//...
}
public void Add(string value)
{
try
{
T typedValue;
typedValue = (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(value);
//Call Add with the converted value
this.Add(typedValue);
}
catch
{
throw;
}
}
}
if you want Add to return default value, use this:
class SomeThing<T>
{
public void Add(T value)
{
//...
}
public void Add(string value)
{
try
{
T typedValue;
typedValue = (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(value);
//Call Add with the converted value
this.Add(typedValue);
}
catch
{
this.Add(default(T));
}
}
}
if you need to convert String to Double like in your example :
String myString = "123456";
Double myDouble
Double.TryParse(text, out myDouble);
TryParse is not only on Double type.
I am trying to write a function to convert the contents of a string "12345" to an int.
If the string is blank i would like to return null (uninitialized), not the value 0.
Problem is, functions do not return un-initialized values.
My code will not compile as Retval can return an uninitialized value......
My attempt so far:
public int ConvertStringToNumber(String TheString)
{
// Uninitialized
int Retval;
if (TheString.Length > 0)
{
// We have a valid string
if (Int32.TryParse(TheString, out Retval))
{
// We have a valid Number
}
}
// Return the number or null
return Retval;
}
Can you use Nullable int ? it will allow set as nullable . See here : http://www.codeproject.com/Articles/11854/C-2-0-Nullable-Types
You can use a nullable int (more info here).
Nullable types can represent all the values of an underlying type, and
an additional null value.
public int? ConvertStringToNumber(String TheString)
{
int retval;
bool isInt = Int32.TryParse(TheString, out retval);
return isInt ? retval : null;
}
Note: When using nullable types, you'll need to use a cast or get it's value. See here.
Example:
int? n = ConvertStringToNumber("123");
int value = n.Value;
// or
int value = (int)n;
If you assigned a value to the Retval object AT THE FIRST TIME, then the value is valid in THAT area ONLY.
So, Retval is null when you return it.
since Int32.TryParse(TheString, out Retval) require int type not nullable
public int? ConvertStringToNumber(String TheString)
{
// Uninitialized
int Retval;
if (TheString.Length > 0)
{
// We have a valid string
if (Int32.TryParse(TheString, out Retval))
{
// We have a valid Number
return Retval;
}
}
// Return the number or null
return null;
}
Simple extension method to resolve your problem
using System;
namespace temp
{
class Program
{
static void Main(string[] args)
{
string valu = "";
Console.WriteLine(valu.ToInt32());
Console.ReadLine();
}
}
public static class MyExtentions
{
public static int ToInt32(this string s)
{
int x;
if (s != null)
{
if (s.Length > 1)
x = Convert.ToInt32(s);
else
x = 0;
}
else
{
x= 0;
}
return x;
}
}
}
int? x = ConvertStringToNumber("1");
int value = x.Value;
String to numeric conversion in c#
I have a class named project with the following data members.
class Project
{
private int Record_Num;
private int GCD_ID;
private string Project_Desc;
private string Proponent_Name;
private string Station_ID;
private string OpCentre;
private string Sector_ID;
private string PLZone;
private string Feeder_ID;
private string DxTx_ID;
private string OpControl_ID;
private string Type_ID;
private string ConnKV_ID;
private string Status_ID;
private double MW;
private string Subject;
private int Ip_Num;
private int H1N_ID;
private int NOMS_Slip_Num;
private DateTime NMS_Updated;
private DateTime Received_Date;
private Nullable<DateTime> Actual_IS_Date;
private string Scheduled_IS_Date;
private string UP_Station_ID;
private string UP_Feeder_ID;
private string HV_Circuit;
}
i query the database and retrieve the values through a data table which assigns the value to the project object like this.
for (int prjIdx = 0; prjIdx < dt.Rows.Count; prjIdx++)
{
newProject = new Project(Convert.ToInt32(dt.Rows[prjIdx]["RecordNum"].ToString()), Convert.ToInt32(dt.Rows[prjIdx]["GCDID"].ToString()),
dt.Rows[prjIdx]["ProjectDesc"].ToString(), dt.Rows[prjIdx]["ProponentName"].ToString(),
dt.Rows[prjIdx]["StationName"].ToString(), dt.Rows[prjIdx]["OpCentre"].ToString(),
dt.Rows[prjIdx]["SectorName"].ToString(), dt.Rows[prjIdx]["PLZone"].ToString(),
dt.Rows[prjIdx]["FeederDesc"].ToString(), dt.Rows[prjIdx]["DxTx"].ToString(),
dt.Rows[prjIdx]["OpControl"].ToString(), dt.Rows[prjIdx]["Type"].ToString(),
dt.Rows[prjIdx]["ConnectionKV"].ToString(), dt.Rows[prjIdx]["Status"].ToString(),
Convert.ToDouble(dt.Rows[prjIdx]["MW"]), dt.Rows[prjIdx]["Subject"].ToString(),
Convert.ToInt32(dt.Rows[prjIdx]["IpNum"]), Convert.ToInt32(dt.Rows[prjIdx]["H1NID"]),
Convert.ToInt32(dt.Rows[prjIdx]["NomsSlipNum"]),Convert.ToDateTime(dt.Rows[prjIdx]["NmsUpdated"]),
Convert.ToDateTime(dt.Rows[prjIdx]["ReceivedDate"]),Convert.ToDateTime(dt.Rows[prjIdx]["ActualIsDate"]),
dt.Rows[prjIdx]["ScheduledIsDate"].ToString(),dt.Rows[prjIdx]["UpStation"].ToString(),dt.Rows[prjIdx]["UpFeeder"].ToString(),
dt.Rows[prjIdx]["HVCircuit"].ToString());
newProject.record_num = Convert.ToInt32(dt.Rows[prjIdx]["RecordNum"]);
projList.Add(newProject);
}
now my problem is, all the date time values retrieved from the database can be null.so if it encounters a null value, it fails to convert it and hence it cannot be assigned in to the object. thus it give me an error
how do i tackle the proble.
should i change the date time variable to string data type. but thats a lame solution. please help//
DateTime is a value-type, you could use the nullable datetime (DateTime?)
MSDN Ref on Nullable Structure
[...]
private int NOMS_Slip_Num;
private DateTime? NMS_Updated;
private DateTime? Received_Date;
private Nullable<DateTime> Actual_IS_Date;
[...]
Doing so will require changes in how you retrieve the value. One way to do so, would be to implement a null or DBNull check, and set the value of nullable datetimes in the Project instanciation using a ternary operator.
public static class Extensions
{
public static bool IsNull(this object o)
{
if (o == null || DBNull.Value.Equals(o))
return true;
else
return false;
}
}
and use it like this in Project's instanciation :
var receivedDate = dt.Rows[prjIdx]["ReceivedDate"];
var actualDate = dt.Rows[prjIdx]["ActualIsDate"];
newProject = new Project([...],
receivedDate.IsNull() ? null : Convert.ToDateTime(receivedDate),
actualDate.IsNull() ? null : Convert.ToDateTime(actualDate),
[...]);
As everyone has already stated you can use Nullable Types in your Model. As for getting them out of the row and checking for DBNull, MS was smart enough to think of this already, and provided a set of extension methods to do just that.
DataRowExtensions.Field Method
...
dt.Rows[prjIdx].Field<Int32?>("IpNum");
...
As long as your underlying type is in fact an int, then this will do the trick.
The Field method does not perform type
conversions. If type conversion is
required, you should first obtain the
column value by using the Field
method. The column value should then
be converted to another type.
Change to nullable DateTime.
I like to keep this utility class around for dealing with DBNull values
public static class DBNullConvert
{
public static T To<T>(object value, T defaultValue)
{
T cast;
try
{
cast = value == DBNull.Value ? defaultValue : (T)value;
}
catch
{
throw new ArgumentException(string.Format("Argument of type {0} cannot be cast to type {1}", value.GetType(), typeof(T)), "value");
}
return cast;
}
public static T To<T>(object value)
{
return To(value, default(T));
}
public static T? ToNullable<T>(object value) where T : struct
{
T? cast;
try
{
cast = value == DBNull.Value ? null : (T?)value;
}
catch
{
throw new ArgumentException(string.Format("Argument of type {0} cannot be cast to type {1}", value.GetType(), typeof(T?)), "value");
}
return cast;
}
public static string ToString(object value)
{
return To(value, String.Empty);
}
}
Then you can use it like this:
DBNullConvert.ToNullable<DateTime>(dt.Rows[prjIdx]["ReceivedDate"])
which will return null if the field is DBNull.Value or the datetime stored in the field if there is one.
As Dynamy stated you can use the
DateTime? which is a Nullable type of date.
Nullable Type C#
N.