I need to declare a Dictionary having a Type as key and an instance as value.
I need to limit key Type to a certain class hierarchy.
For a Java Map, I can do something like:
Map<Class<? extends MySuperClass>, ? extends MySuperClass>
How can I achieve this in C#?
Do not expose Dictionary directly, this way you can control manually when to add
public void AddToDictionary(Type key, object value)
{
if(!key.IsAssignableFrom(typeof(SomeBaseClass))
throw new ArgumentException("Must be an inherited from SomeBaseClass type");
dictionary.Add(key, value);
}
I think Sinatr's approach of exposing a method for adding to the dictionary instead of the dictionary itself is a very good idea. The only downside is that you get no compile time safety; if some code added an object of the wrong type you wouldn't find out till runtime.
Using generics, however, we can tweak the method so that adding objects is foolproof:
public void AddToDictionary<T>(T value) where T: MySuperClass
{
dict.Add(typeof(T), value);
}
Now it is impossible to write a program that adds objects of the wrong type and still compiles.
You could use typeof to get the type of the class so something like:
Map<System.Type, object>
I am not sure how you would enforce the extends for this. That should probably happen as a test before adding to the map.
You could:
public class MyType<TBase>
{
private Type Value;
protected MyType()
{
}
public static implicit operator Type(MyType<TBase> type)
{
return type.Value;
}
public static implicit operator MyType<TBase>(Type type)
{
if (type == null)
{
throw new ArgumentNullException();
}
if (!typeof(TBase).IsAssignableFrom(type))
{
throw new ArgumentException();
}
return new MyType<TBase> { Value = type };
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
var type = obj as MyType<TBase>;
return type != null && Value.Equals(type.Value);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public override string ToString()
{
return Value.ToString();
}
}
and then:
Dictionary<MyType<MySuperClass>, MySuperClass> dict = new Dictionary<MyType<MySuperClass>, MySuperClass>();
dict.Add(typeof(MyClass1), new MyClass1());
The MyType has implicit operators from/to Type, so it is quite simple to use. You simply cast a Type to a MyType (or a MyType to a Type) and it just works. Example of TryGetValue():
MySuperClass ms;
if (!dict.TryGetValue(typeof(MyClass1), out ms))
{
throw new Exception();
}
Note that the checks are done at runtime!
Related
I have a method in which I like to perform a few different casts using reflection mechanism.
private static T GetObject<T>(Dictionary<string, object> dict)
{
Type type = typeof(T);
var obj = Activator.CreateInstance(type);
foreach (var kv in dict)
{
var p = type.GetProperty(kv.Key);
Type t = p.PropertyType;
Type t2 = kv.Value.GetType();
if (t == t2)
{
p.SetValue(obj, kv.Value);
}
else if (!IsPrimitive(p.PropertyType))
{
p.SetValue(obj, GetObject<class of p>((Dictionary<string, object>) kv.Value)); //???
}
else
{
p.SetValue(obj, (primitive)(kv.Value)); //???
}
}
return (T)obj;
}
EDITED
I have a dictionary and I want to convert it to a custom class, each key from dictionary is a property and each dictionary value is the value for that property. The problems appears in two cases, when both, the class property type and dictionary value type are primitives but they have different type (e.g. property is int but dictionary value is long), the second problem appears when property value is another custom class and in that case the dictionary value is always another dictionary
How can I detect dynamically the necessary cast/casts?
Start by looking if the types are assignment compatible with
if (t.IsAssignableFrom(t2))
Otherwise convert with
object converted = Convert.ChangeType(kv.Value, t);
This should handle a lot of cases.
Since you must call the method recursively with a type only know at runtime, it is better to have a non-generic overloaded version of GetObject. The original method only calls the non-generic one
private static T GetObject<T>(Dictionary<string, object> dict)
where T : class, new() // Suggested by Brett Caswell.
{
return (T)GetObject(dict, typeof(T));
}
Note that generic type parameters are always resolved at compile-time. Since you must resolve the type dynamically at run-time, they are more of a hindrance here. You could construct a generic method call using reflection, but I don't see any advantage in doing so. It is complicated and not type safe. Type safety can only be enforced by the compiler.
private static object GetObject(Dictionary<string, object> dict, Type objectType)
{
object obj = Activator.CreateInstance(objectType);
foreach (var kv in dict) {
PropertyInfo prop = objectType.GetProperty(kv.Key);
Type propType = prop.PropertyType;
object value = kv.Value;
if (value == null) {
if (propType.IsValueType) { // Get default value of type.
value = Activator.CreateInstance(propType);
}
} else if (value is Dictionary<string, object> nestedDict) {
value = GetObject(nestedDict, propType);
} else if (!propType.IsAssignableFrom(value.GetType())) {
value = Convert.ChangeType(value, propType);
}
prop.SetValue(obj, value);
}
return obj;
}
Better approach of this problem is apply one of uncle Bob's S.O.L.I.D principle which is Open close principle. Here is the Classic Example of this principle
public abstract class Shape
{
public abstract double Area();
}
public class Rectangle : Shape
{
public double Width { get; set; }
public double Height { get; set; }
public override double Area()
{
return Width*Height;
}
}
public class Circle : Shape
{
public double Radius { get; set; }
public override double Area()
{
return Radius*Radius*Math.PI;
}
}
by this way you don't have to make if else tree but with implementing the abstract class you have to implement Area method every time you use it with any of your Class. Hope that serve the purpose
Update:
I'll accept that to get the code to work Jon's answer to this other question is correct. And this answer answers why an interface is treated like a reference type.
I'd still like to know what the difference is though. Why is an interface not treated like a reference type when it is a generic type constraint? Is their some design reason for this? I have a feeling the only reason may be "they just are".
Original question:
I am converting a class into a generic class but I found some strange behaviour with using an interface as a type parameter. The class has a field and property which are a type of interface, for example IMagic.
public interface IMagic
{
bool Magic { get; }
}
public class HasMagic
{
private IMagic _magic;
public IMagic Magic
{
get { return _magic; }
set
{
if (value != _magic)
_magic = value;
}
}
public bool IsMagical
{
get { return _magic != null ? _magic.Magic : true; }
}
}
I want to change them to instead be type T and have the class defined with the type parameter where T : IMagic. Doing this though gave me a compiler error Operator '!=' cannot be applied to operands of type 'T' and 'T'.
public class HasMagic<T> where T : IMagic
{
private T _magic;
public T Magic
{
get { return _magic; }
set
{
// Compiler error here!
if (value != _magic)
_magic = value;
}
}
public bool IsMagical
{
// But no error here!?
get { return _magic != null ? _magic.Magic : true; }
}
}
So why doesn't the generic version work? Shouldn't == and != operators work for all types?
The error only occurs in the property setter though, so it got me thinking, is the _magic field actually really a boxed IMagic or some other reference type? Indeed it can be set to null which should only work with nullable types. As the test below shows an IMagic struct (MagicStruct) works fine, but why? Changing the field and property in HasMagic to a MagicStruct gives compile errors, as you'd expect.
public class MagicTests
{
[Fact]
public void SomeMagicTest()
{
var mag = new HasMagic();
Assert.True(mag.IsMagical);
mag.Magic = new MagicClass();
Assert.False(mag.IsMagical);
mag.Magic = new MagicStruct();
Assert.True(mag.IsMagical);
mag.Magic = null;
Assert.True(mag.IsMagical);
}
}
public class MagicClass : IMagic
{
public bool Magic { get { return false; } }
}
public struct MagicStruct : IMagic
{
public bool Magic { get { return true; } }
}
If it's of any relevance I'm using .Net framework v4.5.2.
T is a type argument and can be a class or a struct, because of that the compiler won't let you perform actions that doesn't exist in a class or a struct. You can try it like this:
public T Magic
{
get { return _magic; }
set
{
// Compiler error here!
if (!EqualityComparer<T>.Default.Equals(_magic, value))
_magic = value;
}
}
Or you can just use Equals inside your code
public T Magic
{
get { return _magic; }
set
{
// Compiler error here!
if (!value.Equals(_magic))
_magic = value;
}
}
You cannot use != (==) on generic types.
a possible solution would be made IMagic to implement IComparable
public interface IMagic : IComparable
and then use CompareTo
if (value.CompareTo(_magic) != 0)
you can write your own implementation of CompareTo method
public int CompareTo(object obj) {
}
update
if you can't edit IMagic try adding a property to HasMagic class like this
public Func<T, T, bool> FuncEvaluate { get; set; }
and then check in this way
public T Magic
{
get { return _magic; }
set
{
if (FuncEvaluate != null)
{
if (!FuncEvaluate(value, _magic))
{
_magic = value;
}
}
else
{
throw new NotImplementedException();
}
}
}
and when you decide to use the class you should set the function to compare objects maybe checking typeof(T).IsValueType
T can be a value type or a reference type; you didn't contrain it. The != (and ==) operator (reference comparison) is only defined for reference types, not for value types.
There are several solutions; You can constrain T to be a reference type:
public class HasMagic<T> where T : IMagic, class
You can also use Equals(). or object.ReferenceEquals().
And maybe some other solutions I didn't think of.
Edit: I just noticed you don't even need != in the setter, so this whole problem becomes mute.
Is there any way to have a method return any one of a number of generic types from a method? For example, I have the following:
public static T ParseAttributeValue<T>(this XElement element, string attribute)
{
if(typeof(T) == typeof(Int32))
{
return Int32.Parse(element.Attribute(attribute).Value);
}
if(typeof(T) == typeof(Double))
{
return Double.Parse(element.Attribute(attribute).Value);
}
if(typeof(T) == typeof(String))
{
return element.Attribute(attribute).Value;
}
if(typeof(T) == typeof(ItemLookupType))
{
return Enum.Parse(typeof(T), element.Attribute(attribute).Value);
}
}
(This is only a very quick mockup, I'm aware that any production code would need to be significantly more thorough in null checks etc...)
But the compiler doesn't like it, complaining that Int32 cannot be implicitly converted to T (it doesn't work with a cast either). I can understand that. At compile time it has no way to know what T is, but I'm checking it beforehand. Is there anyway I can make this work?
I've done these types of generic methods in the past. The easiest way to get type inference is to provide a generic converter function.
public static T ParseAttributeValue<T>
(this XElement element, string attribute, Func<string, T> converter)
{
string value = element.Attribute(attribute).Value;
if (String.IsNullOrWhiteSpace(value)) {
return default(T);
}
return converter(value);
}
You can use it like the following:
int index = element.ParseAttributeValue("index", Convert.ToInt32);
double price = element.ParseAttributeValue("price", Convert.ToDouble);
You can even provide your own functions and have all the fun in the world (even return anonymous types):
ItemLookupType lookupType = element.ParseAttributeValue("lookupType",
value => Enum.Parse(typeof(ItemLookupType), value));
var item = element.ParseAttributeValue("items",
value => {
List<string> items = new List<string>();
items.AddRange(value.Split(new [] { ',' }));
return items;
});
.Net already has a bunch of great string conversion routines you can use! A TypeConverter can do most of the heavy lifting for you. Then you don't have to worry providing your own parsing implementations for built-in types.
Note that there are locale-aware versions of the APIs on TypeConverter that could be used if you need to handle parsing values expressed in different cultures.
The following code will parse values using the default culture:
using System.ComponentModel;
public static T ParseAttributeValue<T>(this XElement element, string attribute)
{
var converter = TypeDescriptor.GetConverter(typeof(T));
if (converter.CanConvertFrom(typeof(string)))
{
string value = element.Attribute(attribute).Value;
return (T)converter.ConvertFromString(value);
}
return default(T);
}
This will work for a lot of built-in types, and you can decorate custom types with a TypeConverterAttribute to allow them to participate in the type conversion game too. This means that in the future you will be able to parse new types without having to change the implementation of the ParseAttributeValue.
see: http://msdn.microsoft.com/en-us/library/system.componentmodel.typeconverter.aspx
Why are you using the type parameter as the return type at all? This would work, just requires a cast after calling:
public static Object ParseAttributeValue<T>(this XElement element, string attribute)
{
if(typeof(T) == typeof(Int32))
{
return Int32.Parse(element.Attribute(attribute).Value);
}
if(typeof(T) == typeof(Double))
{
return Double.Parse(element.Attribute(attribute).Value);
}
if(typeof(T) == typeof(String))
{
return element.Attribute(attribute).Value;
}
if(typeof(T) == typeof(ItemLookupType))
{
return Enum.Parse(typeof(T), element.Attribute(attribute).Value);
}
}
Or better yet:
public static Int32 ParseAsInt32(this XElement element, string attribute)
{
return Int32.Parse(element.Attribute(attribute).Value);
}
// etc, repeat for each type
This second approach has the additional benefit of having a much higher likelihood of getting inlined, plus it will (for value types like Int32) prevent the need to box/unbox the value. Both of these will cause the method to perform somewhat faster.
Not sure if this is exactly what you want, but you can make the returns work if you cast to object first then to T
public static T ParseAttributeValue<T>(this XElement element, string attribute)
{
if (typeof(T) == typeof(Int32))
{
return (T)(object)Int32.Parse(element.Attribute(attribute).Value);
}
if (typeof(T) == typeof(Double))
{
return (T)(object)Double.Parse(element.Attribute(attribute).Value);
}
if (typeof(T) == typeof(String))
{
return (T)(object)element.Attribute(attribute).Value;
}
return default(T);
}
However you still have to provide T at compile time, calling the method like:
int value = element.ParseAttributeValue<int>("attribute");
Here's two ways of doing it...
static T ReadSetting<T>(string value)
{
object valueObj = null;
if (typeof(T) == typeof(Int32))
valueObj = Int32.Parse(value);
return (T)valueObj;
}
static dynamic ReadSetting2<T>(string value)
{
if (typeof(T) == typeof(Int32))
return Int32.Parse(value);
throw new UnsupportedException("Type is unsupported");
}
static void Main(string[] args)
{
int val1 = ReadSetting<Int32>("2");
int val2 = ReadSetting2<Int32>("3");
}
With C++ templates, this kind of thing would work, but only if each piece of code were in a different, separate specialization. The thing that makes that work is that unused function templates are not compiled (or more accurately: not fully instantiated), so the fact that a piece of code would be invalid if that copy of the template were instantiated with a different type doesn't come up.
C# is different, and AFAIK there's no specialization for generics. One way to accomplish what you are trying to do, while working within the limitations of C# would be to create one function with a more abstract return type, and use the ParseAttributeValue only to cast it to T.
So you would have:
private static Object AbstractParseValue(System.Type t, XElement element, string attribute)
and
public static T ParseAttributeValue<T>(this XElement element, string attribute)
{
return (T)AbstractParseValue(typeof(T), element, attribute);
}
I would suggest that rather than testing the type parameter every time the routine is executed, you should create a generic static class something like this:
internal static class ElementParser<T>
{
public static Func<XElement, string, T> Convert = InitConvert;
T DefaultConvert(XElement element, string attribute)
{
return Default(T); // Or maybe throw exception, or whatever
}
T InitConvert(XElement element, string attribute)
{
if (ElementParser<int>.Convert == ElementParser<int>.InitConvert)
{ // First time here for any type at all
Convert = DefaultConvert; // May overwrite this assignment below
ElementParser<int>.Convert =
(XElement element, string attribute) =>
Int32.Parse(element.Attribute(attribute).Value);
ElementParser<double>.Convert =
(XElement element, string attribute) =>
Int32.Parse(element.Attribute(attribute).Value);
// etc. for other types
}
else // We've done other types, but not this type, and we don't do anything nice for it
{
Convert = DefaultConvert;
}
return Convert(element, attribute);
}
}
public static T ParseAttributeValue(this XElement element, string attribute)
{
ElementParser<T>.Convert(element, attribute);
}
Using this approach, one will only have to do special handling the first time a particular type is used. After that, the conversion can be performed using only a single generic delegate invocation. Once could easily add any number of types, and even allow converters to be registered for any desired type at runtime.
Having the following generic class that would contain either string, int, float, long as the type:
public class MyData<T>
{
private T _data;
public MyData (T value)
{
_data = value;
}
public T Data { get { return _data; } }
}
I am trying to get a list of MyData<T> where each item would be of different T.
I want to be able to access an item from the list and get its value as in the following code:
MyData<> myData = _myList[0]; // Could be <string>, <int>, ...
SomeMethod (myData.Data);
where SomeMethod() is declared as follows:
public void SomeMethod (string value);
public void SomeMethod (int value);
public void SomeMethod (float value);
UPDATE:
SomeMethod() is from another tier class I do not have control of and SomeMethod(object) does not exist.
However, I can't seem to find a way to make the compiler happy.
Any suggestions?
Thank you.
I think the issue that you're having is because you're trying to create a generic type, and then create a list of that generic type. You could accomplish what you're trying to do by contracting out the data types you're trying to support, say as an IData element, and then create your MyData generic with a constraint of IData. The downside to this would be that you would have to create your own data types to represent all the primitive data types you're using (string, int, float, long). It might look something like this:
public class MyData<T, C>
where T : IData<C>
{
public T Data { get; private set; }
public MyData (T value)
{
Data = value;
}
}
public interface IData<T>
{
T Data { get; set; }
void SomeMethod();
}
//you'll need one of these for each data type you wish to support
public class MyString: IData<string>
{
public MyString(String value)
{
Data = value;
}
public void SomeMethod()
{
//code here that uses _data...
Console.WriteLine(Data);
}
public string Data { get; set; }
}
and then you're implementation would be something like:
var myData = new MyData<MyString, string>(new MyString("new string"));
// Could be MyString, MyInt, ...
myData.Data.SomeMethod();
it's a little more work but you get the functionality you were going for.
UPDATE:
remove SomeMethod from your interface and just do this
SomeMethod(myData.Data.Data);
Delegates can really help simplify this, and still keep things type-safe:
public void TestMethod1()
{
Action<SomeClass, int> intInvoke = (o, data) => o.SomeMethod(data);
Action<SomeClass, string> stringInvoke = (o, data) => o.SomeMethod(data);
var list = new List<MyData>
{
new MyData<int> { Data = 10, OnTypedInvoke = intInvoke },
new MyData<string> { Data = "abc", OnTypedInvoke = stringInvoke }
};
var someClass = new SomeClass();
foreach (var item in list)
{
item.OnInvoke(someClass);
}
}
public abstract class MyData
{
public Action<SomeClass> OnInvoke;
}
public class MyData<T> : MyData
{
public T Data { get; set; }
public Action<SomeClass, T> OnTypedInvoke
{ set { OnInvoke = (o) => { value(o, Data); }; } }
}
public class SomeClass
{
public void SomeMethod(string data)
{
Console.WriteLine("string: {0}", data);
}
public void SomeMethod(int data)
{
Console.WriteLine("int: {0}", data);
}
}
Just use an ArrayList and forget the MyData<T> type.
ArrayList myStuff = getStuff();
float x = myStuff.OfType<float>().First();
SomeMethod(x);
string s = myStuff.OfType<string>().First();
SomeMethod(s);
The problem with MyData<T> is that you're expecting the compiler to check a type that is only known at runtime. Compilers check types that are known at compile time.
You can't do it the way you want.
When an instance of a generic class is initialized, it is bound to particular type. Since you want to hold objects of different types in your list, you have to create an instance bound to the least common denominator — in your case it's Object.
However, that means that Data property now will return an object of type Object. The compiler cannot infer the actual data type at compile time, so it can choose the appropriate SomeMethod overload.
You have to either provide an overload of SomeMethod that takes Object as a parameter, or remove the requirement to hold different such different types in your collection.
Or you can go with a standard IEnumerable collection (like Array) and use the OfType<> extension method to get the subset of the collection of particular type.
In that case you need MyData<object> since that is the only thing those types have in common.
You can create a generic wrapper for SomeMethod and check for the type of the generic argument, then delegate to the appropriate method.
public void SomeMethod<T>(T value)
{
Type type = typeof(T);
if (type == typeof(int))
{
SomeMethod((int) (object) value); // sadly we must box it...
}
else if (type == typeof(float))
{
SomeMethod((float) (object) value);
}
else if (type == typeof(string))
{
SomeMethod((string) (object) value);
}
else
{
throw new NotSupportedException(
"SomeMethod is not supported for objects of type " + type);
}
}
Suggested wildcards a while back here. Closed as "won't fix" :(
Generics allow you to specify one type for the whole list when you create the list, for example a list for storing int would be created like this
var myData = new MyData<int>();
If you want to store multiple types in the same generic list you can specify a common base type or interface for those types. Unfortunately in your case the only common base type for the types you want to store would be object.
var myData = new MyData<object>();
But you can just use the non-generic list for storing objects.
Inherit MyData<T> from a non-generic MyData class and make a list of that.
This way, you can't automatically resolve the overload. You have to do it manually.
abstract class MyData {
protected abstract object GetData();
protected abstract Type GetDataType();
public object Data {
get { return GetData(); }
}
public Type DataType {
get { return GetDataType(); }
}
}
class MyData<T> : MyData {
protected override object GetData() { return Data; }
protected override Type GetDataType() { return typeof(T); }
public new T Data {
get { ... }
}
}
I have a class that I want to use to store "properties" for another class. These properties simply have a name and a value. Ideally, what I would like is to be able to add typed properties, so that the "value" returned is always of the type that I want it to be.
The type should always be a primitive. This class subclasses an abstract class which basically stores the name and value as string. The idea being that this subclass will add some type-safety to the base class (as well as saving me on some conversion).
So, I have created a class which is (roughly) this:
public class TypedProperty<DataType> : Property
{
public DataType TypedValue
{
get { // Having problems here! }
set { base.Value = value.ToString();}
}
}
So the question is:
Is there a "generic" way to convert from string back to a primitive?
I can't seem to find any generic interface that links the conversion across the board (something like ITryParsable would have been ideal!).
I am not sure whether I understood your intentions correctly, but let's see if this one helps.
public class TypedProperty<T> : Property where T : IConvertible
{
public T TypedValue
{
get { return (T)Convert.ChangeType(base.Value, typeof(T)); }
set { base.Value = value.ToString();}
}
}
lubos hasko's method fails for nullables. The method below will work for nullables. I didn't come up with it, though. I found it via Google: http://web.archive.org/web/20101214042641/http://dogaoztuzun.com/post/C-Generic-Type-Conversion.aspx Credit to "Tuna Toksoz"
Usage first:
TConverter.ChangeType<T>(StringValue);
The class is below.
public static class TConverter
{
public static T ChangeType<T>(object value)
{
return (T)ChangeType(typeof(T), value);
}
public static object ChangeType(Type t, object value)
{
TypeConverter tc = TypeDescriptor.GetConverter(t);
return tc.ConvertFrom(value);
}
public static void RegisterTypeConverter<T, TC>() where TC : TypeConverter
{
TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
}
}
For many types (integer, double, DateTime etc), there is a static Parse method. You can invoke it using reflection:
MethodInfo m = typeof(T).GetMethod("Parse", new Type[] { typeof(string) } );
if (m != null)
{
return m.Invoke(null, new object[] { base.Value });
}
TypeDescriptor.GetConverter(PropertyObject).ConvertFrom(Value)
TypeDescriptor is class having method GetConvertor which accept a Type object and then you can call ConvertFrom method to convert the value for that specified object.
With inspiration from the Bob's answer, these extensions also support null value conversion and all primitive conversion back and fourth.
public static class ConversionExtensions
{
public static object Convert(this object value, Type t)
{
Type underlyingType = Nullable.GetUnderlyingType(t);
if (underlyingType != null && value == null)
{
return null;
}
Type basetype = underlyingType == null ? t : underlyingType;
return System.Convert.ChangeType(value, basetype);
}
public static T Convert<T>(this object value)
{
return (T)value.Convert(typeof(T));
}
}
Examples
string stringValue = null;
int? intResult = stringValue.Convert<int?>();
int? intValue = null;
var strResult = intValue.Convert<string>();
You could possibly use a construct such as a traits class. In this way, you would have a parameterised helper class that knows how to convert a string to a value of its own type. Then your getter might look like this:
get { return StringConverter<DataType>.FromString(base.Value); }
Now, I must point out that my experience with parameterised types is limited to C++ and its templates, but I imagine there is some way to do the same sort of thing using C# generics.
Check the static Nullable.GetUnderlyingType.
- If the underlying type is null, then the template parameter is not Nullable, and we can use that type directly
- If the underlying type is not null, then use the underlying type in the conversion.
Seems to work for me:
public object Get( string _toparse, Type _t )
{
// Test for Nullable<T> and return the base type instead:
Type undertype = Nullable.GetUnderlyingType(_t);
Type basetype = undertype == null ? _t : undertype;
return Convert.ChangeType(_toparse, basetype);
}
public T Get<T>(string _key)
{
return (T)Get(_key, typeof(T));
}
public void test()
{
int x = Get<int>("14");
int? nx = Get<Nullable<int>>("14");
}
I used lobos answer and it works. But I had a problem with the conversion of doubles because of the culture settings. So I added
return (T)Convert.ChangeType(base.Value, typeof(T), CultureInfo.InvariantCulture);
public class TypedProperty<T> : Property
{
public T TypedValue
{
get { return (T)(object)base.Value; }
set { base.Value = value.ToString();}
}
}
I using converting via an object. It is a little bit simpler.
Yet another variation. Handles Nullables, as well as situations where the string is null and T is not nullable.
public class TypedProperty<T> : Property where T : IConvertible
{
public T TypedValue
{
get
{
if (base.Value == null) return default(T);
var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
return (T)Convert.ChangeType(base.Value, type);
}
set { base.Value = value.ToString(); }
}
}
You can do it in one line as below:
YourClass obj = (YourClass)Convert.ChangeType(YourValue, typeof(YourClass));
Happy coding ;)