C# Generic type comparison - c#

I have this code:
public class myList<T> where T : struct
{
public int number { get; set; }
}
public class TypeTest
{
public static int GetNumber(object x)
{
// if (x.GetType() == typeof(myList<>)) // this works BUT I want to use is
if (x is myList<>) // how is the correct syntax for this?
{
int result = ((myList<>)x).numb; //does not compile
return result;
}
return 0;
}
}
But some generic syntax issues.
Question: What is the correct Syntax for this?

It would be nice to re-declare your method as a generic one:
public static T GetNumber<T>(myList<T> myList) where T : struct
Doing so you would avoid any casts and the method's body would become one-liner as below:
return myList?.numb ?? 0;

You can check if the object is of your open generic type as explained in Testing if object is of generic type in C#, and then get the property named "number" from the actual type:
var typeOfX = x.GetType();
if (typeOfX.GetGenericTypeDefinition() == typeof(myList<>))
{
var numberProperty = typeOfX.GetProperty("number");
var propertyValue = numberProperty.GetValue(x);
return (int)propertyValue;
}
Do note that this code lacks any error handling, such as missing property or a property not of the expected type. That's the price you pay for being forced to use reflection.

Related

using dynamic keyword to cast to a value type...throws exception

Sorry for the long question :
I have some classes that all have InnerObject as a property.
public class MyInt
{
int InnerObject;
}
public class MyLong
{
long InnerObject;
}
public class MyString
{
string InnerObject;
}
and so on ...
Please don't tell me I can use generics, or Don't ask me why I need these classes. Please read my question.
I have a some class called Foo that has a method called ProcessSomething :
public class Foo
{
void Process(MyInt value)
{
...
}
}
Now I have a framework code where I want to write some code like this -
I want to write code like this :
int myValue = 100;
MyInt myInt = new MyInt();
myInt.InnerObject = myValue;
myFoo.Process(myValue );
SO far so good but I have many different types of classes and their functions where I may have to pass MyString, MyLong etc....
So to ease this I tried to create a Utility class like this :
public static class MyTypes
{
public static dynamic Convert<T>(T i)
{
dynamic x = new ExpandoObject();
x.InnerObject = i;
return x;
}
}
My intention was that I could write code like this :
myFoo.Process(MyTypes.Convert<int>(myValue));
All this code compiles ,as expected, but at runtime I get an exception when I the above line is executed .
Cannot implicitly convert type 'System.Dynamic.ExpandoObject' to 'iInt32'
When I try to modify my Convert method to this :
public static K Convert<T,K>(T i)
{
dynamic x = new ExpandoObject();
x.InnerObject = i;
return (K)x;
}
and call it like this ( even though I don't like it, but I tried to see if I can make it work)
myFoo.Process(MyTypes.Convert(myValue));
I still get the exception :
Cannot convert type 'System.Dynamic.ExpandoObject' to 'iInt32'
Clearly I am not understanding something..Any help in clarifying my understanding would be much appreciated.
Don't create ExpandoObject, it's not MyInt, MyLong, etc., so it cannot be cast to these classes.
You can add a new constraint to MyTypes.Convert<T>, and use new T() to create an object to return:
public static K Convert<T,K>(T i) where K : new()
{
dynamic x = new K();
x.InnerObject = i;
return (K)x;
}
I'm not sure I understand what you are trying to accomplish or if it's possible, but I can shed some light on the problem.
dynamic x = new ExpandoObject();
x.InnerObject = i;
return (K)x;
When you invoke this code using int for the generic type parameter K, then the last line will attempt to cast an ExpandoObject to an int. There's no such conversion defined, so it fails.
Is there some reason you can't use myFoo.Process(new MyInt(...))?

Getting type of field (none instance)

Can I get the type of a field? Type.GetType(); only returns the type of an instance, so if field is set null I cant get the Type.
Note: I would prefer not using reflections~
Depending on context GetProperty and PropertyType may work for you. I.e. if you have object type and property name:
var typeOfLength = typeof(String).GetProperty("Length").PropertyType;
It's not clear whether you only want the compile time type when the field is null. A simple method like this could work:
public static class ReflectionExtensions
{
public static Type GetCompileTimeType<T>(this T obj)
{
return typeof(T);
}
}
You could modify it it check for null and return the actual type if that is what you want.
usage:
class A { }
class B : A { }
class C
{
private A a1, a2;
public C()
{
a2 = new B();
Console.WriteLine(a1.GetCompileTimeType()); // null but prints A
Console.WriteLine(a2.GetCompileTimeType()); // actually a B but prints A
}
}
public class test
{
private int fTestInt;
private string fTestString;
}
You can achieve getting the field type by typing fTestInt.GetType().
If you want a quick type validation you can use.
if (fTestInt is int)
{
Console.Write("I'm an int!");
}
Not sure if this is what you're asking. Your question seems partial.
Why not just ask if is null ?
if (Type != null)
{
return Type.GetType().Name;
}
else
{
return "";
}

Verify the type of custom class in function

In C#,I have a public function that can pass a List parameter, with T is a custom class. The function can pass with different T class. The problem that how to verify the type of T in every case?
public static List<T> ConvertData(List<T> oldDatas)
{
//I will analyze the object T,
//but now i don't know how to verify the type of T,
//with T can change,
//example maybe T is T1 class,or T2 class..
}
Thanks for my stupid question.
this is for C#
Type gt = typeof(T);
check this for java : Get generic type of java.util.List
just do :
public static class Test<T>
where T : class, new()
{
public static List<T> ConvertData(List<T> oldDatas)
{
T instanceOfT = new T();
Type typeOfT = typeof(T); // or instanceOfT.GetType();
if(instanceOfT is string)
{
// T is a string
}
else if(instanceOfT is int)
{
// T is an int
}
// ...
}
}
But that isn't productive and break the generic concept... Explain what you're trying to do.
Do you need to make different converting depends on or just want to check for specific classes? In second case you can try to specify right types for T something like:
public static List<string> ConvertData(List<string> data)
{
return PrivateConvertData<string>(data);
}
public static List<int> ConvertData(List<int> data)
{
return PrivateConvertData<int>(data);
}
private static List<T> PrivateConvertData<T>(List<T> data)
{
// code here
}
This code will check type of T during compilation.
You can use the typeof(T) keyword or use some check (if you are expecting some types to be passed via parameters):
public static List<T> ConvertData(List<T> oldDatas)
{
foreach (var itemList in oldDatas)
{
if (itemList is LinqType)
{
var linqTypeItem = (LinqType) itemList;
Console.WriteLine(linqTypeItem.PROPERTY_YOU_NEED);
}
// or
var linqTypeItem = itemList as LinqType;
if (linqTypeItem != null)
{
Console.WriteLine(linqTypeItem.PROPERTY_YOU_NEED);
}
}
}
Also you can use the Cast() method. More information here

Derived interface from generic method

I'm trying to do this:
public interface IVirtualInterface{ }
public interface IFabricationInfo : IVirtualInterface
{
int Type { get; set; }
int Requirement { get; set; }
}
public interface ICoatingInfo : IVirtualInterface
{
int Type { get; set; }
int Requirement { get; set; }
}
public class FabInfo : IFabricationInfo
{
public int Requirement
{
get { return 1; }
set { }
}
public int Type
{
get {return 1;}
set{}
}
}
public class CoatInfo : ICoatingInfo
{
public int Type
{
get { return 1; }
set { }
}
public int Requirement
{
get { return 1; }
set { }
}
}
public class BusinessObj
{
public T VirtualInterface<T>() where T : IVirtualInterface
{
Type targetInterface = typeof(T);
if (targetInterface.IsAssignableFrom(typeof(IFabricationInfo)))
{
var oFI = new FabInfo();
return (T)oFI;
}
if (targetInterface.IsAssignableFrom(typeof(ICoatingInfo)))
{
var oCI = new CoatInfo();
return (T)oCI;
}
return default(T);
}
}
But getting a compiler error: Canot convert type 'GenericIntf.FabInfo' to T
How do I fix this?
thanks
Sunit
Assuming all IVirtualInterface implementations will have a default constructor (as in your example), you can do this instead:
public T VirtualInterface<T>() where T : IVirtualInterface, new()
{
return new T();
}
Simples!
EDIT:
Exactly what you're trying to achieve is difficult to determine from the code you've posted. Why isn't VirtualInterface static (implies all business objects inherit this method which seems odd)? If you need o be able to parameterised constructors for your IVirtualInterface implementations, where would those parameter values come from (you're not passing any into the VirtualInterface method)?
If you just want to avoid cluttering up intellisense (a poor reason for trying something like this IMHO) but also want to maintain support for parameteried constructors, then how about this:
public T VirtualInterface<T>(Func<T> constructor) where T : IVirtualInterface
{
return constructor();
}
With usage:
IFabricationInfo fabInfo =
new BusinessObj().VirtualInterface<IFabricationInfo>(() => new FabInfo());
Overall though, and without enough information to make a solid judgement, I'd have to say that this smells.
The fact that T and FabInfo both implement IVirtualInterface does not mean you can perform a cast between the two types. For example if T is CoatInfo, then it is not compatible type with FabInfo.
Interfaces allow you to treat different objects as similar types based on the methods they provide. However, this does not mean that you can perform casts between these two types as their actual implementation can vary greatly.
Edit: After re-reading your method again, I see that you are checking the type first. The problem is that the compiler doesn't know you are performing that logic before you try to make that cast. If you are writing a generic method and are checking the type of T, you are likely misusing the concept of generics. See the other answers for the way you should be creating new instances of T.
You can get around this error by first casting to object before casting to T e.g.
return (T)(object)oFI;
and similarly for CoatInfo
However I think switching on a generic type is an abuse, since if you want a limited number of possible return values, you could make the options explicit e.g.
public IFabricationInfo GetFabricationInfo()
{
return new FabInfo();
}

Generic type conversion FROM string

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 ;)

Categories

Resources