Inverse .ToString() - c#

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.

Related

convert String Type to int,float,decimal etc Type on runtime C#

I have made a program in which i wanted to convert all values depending on parameters type which is get by run time methods, what i want is convert all values which are enter by user in textbox in define type of parameter.
what i wanted is
private object convertType(Type type, string value)
{
Type t = typeof(int);
//suppose value have stringvalue=33;
return 33; //of type int
}
is there any way to get any object type ?
Updated Answer
for #Atmane EL BOUACHRI,
class Program
{
static void Main()
{
var ints = ConvertType<int>("33");
var bools = ConvertType<bool>("false");
var decimals = ConvertType<decimal>("1.33m"); // exception here
Console.WriteLine(ints);
Console.WriteLine(bools);
Console.WriteLine(decimals);
Console.ReadLine();
}
public static T ConvertType<T>(string input)
{
T result = default(T);
var converter = TypeDescriptor.GetConverter(typeof(T));
if (converter != null)
{
try
{
result = (T)converter.ConvertFromString(input);
}
catch
{
// add you exception handling
}
}
return result;
}
}
Here I don't want hard code <int>, <string> or <decimal>, what I want is
private object convertToAnyType(Type type, string value)
{
//Type t = typeof(int);
return ConvertType<type>("33");
}
Is there any way??
You mean certainly return string value parsed to a specific Type. Then , I propose generics. Here's how :
1)- Without Generics (I Prefer With Generic in 2)-)
class Program
{
static void Main()
{
var ints = (int)ConvertType(typeof(int),"33");
var bools = (bool)ConvertType(typeof(bool), "true");
Console.WriteLine(bools);
Console.WriteLine(ints);
Console.ReadLine();
}
public static object ConvertType(Type type, string input)
{
object result = default(object);
var converter = TypeDescriptor.GetConverter(type);
if (converter != null)
{
try
{
result = converter.ConvertFromString(input);
}
catch
{
// add you exception handling
}
}
return result;
}
}
2)-With Generic
class Program
{
static void Main()
{
var ints = ConvertType<int>("33");
var bools = ConvertType<bool>("false");
var decimals = ConvertType<decimal>("1.33m"); // exception here
Console.WriteLine(ints);
Console.WriteLine(bools);
Console.WriteLine(decimals);
Console.ReadLine();
}
public static T ConvertType<T>(string input)
{
T result = default(T);
var converter = TypeDescriptor.GetConverter(typeof(T));
if (converter != null)
{
try
{
result = (T)converter.ConvertFromString(input);
}
catch
{
// add you exception handling
}
}
return result;
}
}
Hpe it helps

How can I make a switch statement more object oriented? [duplicate]

This question already has answers here:
Is there a better alternative than this to 'switch on type'?
(31 answers)
Is it possible to use the instanceof operator in a switch statement?
(26 answers)
Closed 7 years ago.
I am trying to refactor a switch statement that is like this:
private void Validate(DataTypeEnum dataType, string value, ...)
{
switch(dataType)
{
case DataTypeEnum.Number:
var typedValue = int.Parse(value);
//Validation of typedValue
break;
case DataTypeEnum.Decimal:
var typedValue = Decimal.Parse(value);
//Validation of typedValue
break;
case DataTypeEnum.DateTime:
var typedValue = DateTime.Parse(value);
//Validation of typedValue
break;
}
}
I would like to get rid of the switch statement and somehow replace it with a more object oriented construct. Any suggestions?
My ideal would be something like this:
private void Validate(DataTypeEnum dataType, string value, ...)
{
Validate(value);
}
private void (Decimal value)
{
//Validate
}
private void (DateTime value)
{
//Validate
}
Is there any elegant way to fix this?
Use polymorphism.
Example:
public class DataType
{
public virtual void Validate()
{
Console.WriteLine("Performing base class validation tasks");
}
}
class Foo : DataType
{
public override void Validate()
{
// Code to validate a foo...
Console.WriteLine("Validating a foo");
}
}
class Bar : DataType
{
public override void Validate()
{
// Code to validate a bar...
Console.WriteLine("Validating a bar");
}
}
List<DataType> datatypes = new List<DataType>();
datatypes.Add(new Foo());
datatypes.Add(new Barr());
foreach (DataType s in datatypes)
{
s.Validate();
}
To add to this, while some might consider this not OOP at all, you can use dynamic overloads to handle this:
public bool ValidateAny(dynamic val)
{
return Validate(val);
}
private bool Validate(string val) { ... }
private bool Validate(int val) { ... }
private bool Validate(decimal val) { ... }
private bool Validate(object val) { ... } // This is the fallback
Basically, this works the same as usual overload resolution, but it's performed at runtime, depending on the runtime type of the val in ValidateAny.
For example:
ValidateAny(3); // Uses the int overload
ValidateAny((object)3); // Uses the int overload as well - dynamic handles the unboxing
ValidateAny(3M); // Uses the decimal overload
ValidateAny(3.ToString()); // Uses the string overload
ValidateAny(3f); // Uses the object overload, since there's no better match
This is incredibly powerful, as long as you only ever need to have different validations for different types. If you also have other considerations, this must at some level go back to if/switch. Even then it can save you a lot of time, though.
First of all I'd start with implementing simple interface for validation:
public interface IValidator
{
bool Validate(object value);
}
Then number validator may look like this:
public class NumberValidator : IValidator
{
public bool Validate(object value)
{
return (int) value > 0;
}
}
And final step replacing your switch with dictionary:
var _validators = new Dictionary<DataTypeEnum, IValidator> // injected via DI
{
{ DataTypeEnum.Number, new NumberValidator() },
{ DataTypeEnum.DateTime, new DateTimeValidator() },
{ DataTypeEnum.String, new StringValidator() }
};
......
private bool Validate(DataTypeEnum dataType, object value, ...)
{
if (_validators.ContainsKey(dataType))
{
return _validators[dataType].Validate(value);
}
return false;
}
public interface IValidator
{
void Validate(object value);
}
public class NumberValidator : IValidator
{
public void Validate(object value)
{
//implementation
}
}
public class DecimalValidator : IValidator
{
public void Validate(object value)
{
//implementation
}
}
public class DatetimeValidator : IValidator
{
public void Validate(object value)
{
//implementation
}
}
private void Validate(IValidator validator, object value)
{
validator.Validate(value);
}
Create a Dictionary that has DataTypeEnum as Key and Action as Value. Then Get the Value from Dictionary by Key and Invoke The action.
private readonly Dictionary<DataTypeEnum , Action > Validator = new Dictionary<DataTypeEnum , Action >
{
{ DataTypeEnum.Number, () => Validate(Convert.ToDouble((string)value)) },
{ DataTypeEnum.Decimal, () => Validate(Convert.ToDecimal((string)value)) },
{ DataTypeEnum.DateTime, () => Validate(Convert.ToDateTime((string)value)) },
// ...
}
private void Validate(DataTypeEnum dataType, object value, ...)
{
Validator[dataType](); // Gets the Action and Invokes it
}
private void Validate (Decimal value)
{
//Validate
}
private void Validate (DateTime value)
{
//Validate
}
//...
Here the Action is Void delegate that takes no parameters. It will convert value to suitable format and calls Validate Method.
private void Validate<T>(T value) where T : IComparable
{
if(value is Number)
{
}
if(value is Decimal)
{
}
if(value is DateTime)
{
}
}
How about something like this:
private void Validate(object value, ...)
{
if(Reference.Equals(null, value)
return;
if(value is Number)
{
}
else if(value is Decimal)
{
}
else if (value is DateTime)
{
}
else return;
}
If the value passed in is either Number, Decimal or DateTime it will run the appropriate method, other wise it will simply return.

How can I access to the method in class that returns a Generic Type

I have a class named config with two string fields named key paramValue and parameterPath.
When I apply the ChooseType method of the class, the method has to return one variable paramValue in different types (Int or bool or String).
I implemented it as follow:
class ConfigValue
{
public string paramPath;
private string paramValue;
public enum RetType {RetInt, RetBool, RetString};
public T PolimorphProperty<T>(RetType how)
{
{
switch (how)
{
case RetType.RetInt:
return (dynamic)int.Parse(paramValue);
case RetType.RetBool:
return (dynamic)Boolean.Parse(paramValue);
case RetType.RetString:
return (T)(object)paramValue;
default:
throw new ArgumentException("RetType not supported", "how");
}
}
}
}
My question is how can i access to the PolimorphProperty method in ConfigValue class, to retrive for examlple paramValue Int type.
Having both T and RetType is redundant. It should be something like this:
class ConfigValue
{
public string paramPath;
private string paramValue;
public T PolimorphProperty<T>()
{
return (T)Convert.ChangeType(paramValue, typeof(T));
}
}
Call it like configValue.PolimorphProperty<int>().
Or if you need to implement the type conversion manually, you can do something like this:
class ConfigValue
{
public string paramPath;
private string paramValue;
public T PolimorphProperty<T>()
{
if (typeof(T) == typeof(MySpecialType))
return (T)(object)new MySpecialType(paramValue);
else
return (T)Convert.ChangeType(paramValue, typeof(T));
}
}
I think following code best matches what you want (i have tested it before writing here...)
public T PolimorphProperty<T>()
{
object tt = Convert.ChangeType(paramValue, typeof(T));
if (tt == null)
return default(T);
return (T) tt;
}
And you can call the code like this:
int ret = cv.PolimorphProperty<int>();
Notes:
You really do not need to pass anything in the param list to determine the type of the returned value.
Make sure you put try-catch wherever you are checking the appropraite type for your future usage.

How to use the AS keyword with unknown type

I am trying to use the AS keyword with an unknown type. Here is my code:
public GetData(Type MyType, string CSVPath)
{
var engine = new FileHelperEngine(MyType);
try
{
_Data = engine.ReadFile(CSVPath) as MyType; //error here
}
catch(Exception ex)
{
Console.WriteLine("Error occured: " + ex.Message);
}
}
as you can see in this code I am getting an error were MyType is. Is there a better way to do this
Use a generic method instead of passing in a Type as a parameter:
public void GetData<T>(string CSVPath)
{
var engine = new FileHelperEngine(typeof(T));
_Data = engine.ReadFile(CSVPath) as T;
if (_Data != null)
{
//correct type, do the rest of your stuff here
}
}
I'm not sure I understand. First, using as doesn't throw an exception, it just returns null.
Second, I'm pretty sure you don't want to cast, you just want to check the type, so you need the is operator. But since MyType is only known at runtime, you indeed need reflection. It's quite simple:
object o = engine.Readfile(CSVPath);
if(MyType.IsAssignableFrom(o.GetType())
_Data = o;
else
Console.WriteLine("Mismatching types: {0} is not of type {1}", o.GetType(), MyType);
Note: I'm assuming _Data is of type object, otherwise, you just use the as operator with _Data's type.
Here's a class that does this, though I have a hard time thinking of a good case for a dynamic cast like this.:
using System;
namespace Test
{
class Program
{
private object _data;
static void Main(string[] args)
{
new Program().EntryPoint();
}
public void EntryPoint()
{
GetData(typeof(string), "Test");
Console.WriteLine(_data);
}
public void GetData(Type myType, string csvPath)
{
var engine = new FileHelperEngine(myType, csvPath);
// This is the line that does it.
_data = Convert.ChangeType(engine.ReadFile(csvPath), myType);
}
private class FileHelperEngine
{
public string Value { get; set; }
public FileHelperEngine(Type t, string value) { Value = value.ToString(); }
public string ReadFile(string path) { return Value; }
}
}
}

Creating a generic method in C#

I am trying to combine a bunch of similar methods into a generic method. I have several methods that return the value of a querystring, or null if that querystring does not exist or is not in the correct format. This would be easy enough if all the types were natively nullable, but I have to use the nullable generic type for integers and dates.
Here's what I have now. However, it will pass back a 0 if a numeric value is invalid, and that unfortunately is a valid value in my scenarios. Can somebody help me out? Thanks!
public static T GetQueryString<T>(string key) where T : IConvertible
{
T result = default(T);
if (String.IsNullOrEmpty(HttpContext.Current.Request.QueryString[key]) == false)
{
string value = HttpContext.Current.Request.QueryString[key];
try
{
result = (T)Convert.ChangeType(value, typeof(T));
}
catch
{
//Could not convert. Pass back default value...
result = default(T);
}
}
return result;
}
What if you specified the default value to return, instead of using default(T)?
public static T GetQueryString<T>(string key, T defaultValue) {...}
It makes calling it easier too:
var intValue = GetQueryString("intParm", Int32.MinValue);
var strValue = GetQueryString("strParm", "");
var dtmValue = GetQueryString("dtmPatm", DateTime.Now); // eg use today's date if not specified
The downside being you need magic values to denote invalid/missing querystring values.
I know, I know, but...
public static bool TryGetQueryString<T>(string key, out T queryString)
What about this? Change the return type from T to Nullable<T>
public static Nullable<T> GetQueryString<T>(string key) where T : struct, IConvertible
{
T result = default(T);
if (String.IsNullOrEmpty(HttpContext.Current.Request.QueryString[key]) == false)
{
string value = HttpContext.Current.Request.QueryString[key];
try
{
result = (T)Convert.ChangeType(value, typeof(T));
}
catch
{
//Could not convert. Pass back default value...
result = default(T);
}
}
return result;
}
Convert.ChangeType() doesn't correctly handle nullable types or enumerations in .NET 2.0 BCL (I think it's fixed for BCL 4.0 though). Rather than make the outer implementation more complex, make the converter do more work for you. Here's an implementation I use:
public static class Converter
{
public static T ConvertTo<T>(object value)
{
return ConvertTo(value, default(T));
}
public static T ConvertTo<T>(object value, T defaultValue)
{
if (value == DBNull.Value)
{
return defaultValue;
}
return (T) ChangeType(value, typeof(T));
}
public static object ChangeType(object value, Type conversionType)
{
if (conversionType == null)
{
throw new ArgumentNullException("conversionType");
}
// if it's not a nullable type, just pass through the parameters to Convert.ChangeType
if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
// null input returns null output regardless of base type
if (value == null)
{
return null;
}
// it's a nullable type, and not null, which means it can be converted to its underlying type,
// so overwrite the passed-in conversion type with this underlying type
conversionType = Nullable.GetUnderlyingType(conversionType);
}
else if (conversionType.IsEnum)
{
// strings require Parse method
if (value is string)
{
return Enum.Parse(conversionType, (string) value);
}
// primitive types can be instantiated using ToObject
else if (value is int || value is uint || value is short || value is ushort ||
value is byte || value is sbyte || value is long || value is ulong)
{
return Enum.ToObject(conversionType, value);
}
else
{
throw new ArgumentException(String.Format("Value cannot be converted to {0} - current type is " +
"not supported for enum conversions.", conversionType.FullName));
}
}
return Convert.ChangeType(value, conversionType);
}
}
Then your implementation of GetQueryString<T> can be:
public static T GetQueryString<T>(string key)
{
T result = default(T);
string value = HttpContext.Current.Request.QueryString[key];
if (!String.IsNullOrEmpty(value))
{
try
{
result = Converter.ConvertTo<T>(value);
}
catch
{
//Could not convert. Pass back default value...
result = default(T);
}
}
return result;
}
You can use sort of Maybe monad (though I'd prefer Jay's answer)
public class Maybe<T>
{
private readonly T _value;
public Maybe(T value)
{
_value = value;
IsNothing = false;
}
public Maybe()
{
IsNothing = true;
}
public bool IsNothing { get; private set; }
public T Value
{
get
{
if (IsNothing)
{
throw new InvalidOperationException("Value doesn't exist");
}
return _value;
}
}
public override bool Equals(object other)
{
if (IsNothing)
{
return (other == null);
}
if (other == null)
{
return false;
}
return _value.Equals(other);
}
public override int GetHashCode()
{
if (IsNothing)
{
return 0;
}
return _value.GetHashCode();
}
public override string ToString()
{
if (IsNothing)
{
return "";
}
return _value.ToString();
}
public static implicit operator Maybe<T>(T value)
{
return new Maybe<T>(value);
}
public static explicit operator T(Maybe<T> value)
{
return value.Value;
}
}
Your method would look like:
public static Maybe<T> GetQueryString<T>(string key) where T : IConvertible
{
if (String.IsNullOrEmpty(HttpContext.Current.Request.QueryString[key]) == false)
{
string value = HttpContext.Current.Request.QueryString[key];
try
{
return (T)Convert.ChangeType(value, typeof(T));
}
catch
{
//Could not convert. Pass back default value...
return new Maybe<T>();
}
}
return new Maybe<T>();
}
I like to start with a class like this
class settings
{
public int X {get;set;}
public string Y { get; set; }
// repeat as necessary
public settings()
{
this.X = defaultForX;
this.Y = defaultForY;
// repeat ...
}
public void Parse(Uri uri)
{
// parse values from query string.
// if you need to distinguish from default vs. specified, add an appropriate property
}
This has worked well on 100's of projects. You can use one of the many other parsing solutions to parse values.

Categories