Getting type of field (none instance) - c#

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 "";
}

Related

C# Generic type comparison

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.

Type variable at function

Good day!
This question seems easy, but I can't think out how to do it. I would pass Type parameter to function and check whether variable has that type.
void foo(Type type = ) // how to pass here default value for example System.Object?
{
if (elem.GetType() is type)
{
}
}
}
EDIT I have next classes
class Element {}
class ChildElementClass : Element {}
class SecondChildEleementClass : Element{}
And have array of Elements[], which is storing elements of all three classes
Element[] elements;
So, I would retrieve all elements for ChildElementClass. I make it by other way, but it is just interesting.
Use this:
void foo(Type type = null)
{
if (type == null)
type = typeof(object);
}
See: here
you could create a helper method to pass a default value
public void foo(){
foo(typeof(object));
}
private void foo(Type type){
//
}
or, set the default type as null and specify a default inside the method
if (type == null) {
type = typeof(object);
}

Compile error using an interface as a generic type constraint

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.

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

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