Type variable at function - c#

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

Related

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

C# Using Reflection With Generic Property

I have a class which uses generic properties. For example:
class Person
{
public MyGenericProperty<string> Field1
{
get { return field1; }
set { field1 = value; }
}
private MyGenericProperty<string> field1= new MyInheritedGenericProperty<string>("Alan1");
}
I want to use this class with reflection at another class and i have a method like that
public void DoSomethingWithProperty(object sourceobject)
{
foreach (var aProperty in sourceobject.GetType().GetProperties())
{
*if(aProperty.PropertyType == typeof(MyGenericProperty<>))*
{
*var obj = (MyGenericProperty<>)aProperty.GetValue(sourceobject, null);*
}
}
return null;
}
I have two problem
1- How can do type check of generic property. In that example code of if(aProperty.PropertyType == typeof(MyGenericProperty<>)) does not work.
2- T of MyGenericProperty could be any class and how can cast MyGenericProperty class without knowing T by reflection as
var obj = (MyGenericProperty<>)aProperty.GetValue(sourceobject, null);
Thank for helps.
Firstly, it's important to understand that you don't have a "generic property" - there's no such thing. You have a property whose type is a generic type... and that's not the same thing. (Compare that with a generic type or a generic method, each of which is genuinely generic in terms of introducing new type parameters.)
You can test it using this code:
if (aProperty.PropertyType.IsGenericType &&
aProperty.GetGenericTypeDefinition() == typeof(MyGenericProperty<>))
But as for the casting - it depends on what you want to do with the value afterwards. You may want to declare a non-generic base type of MyGenericProperty<> containing all the members which don't depend on the type parameter. I'd typically give that the same name as the generic type (e.g. MyGenericProperty) just without giving it type parameters. Then if you only need one of those members, you can use:
if (aProperty.PropertyType.IsGenericType &&
aProperty.GetGenericTypeDefinition() == typeof(MyGenericProperty<>))
{
var value = (MyGenericProperty) aProperty.GetValue(sourceObject, null);
// Use value
}
But then in that case you could use Type.IsAssignableFrom anyway:
if (typeof(MyGenericProperty).IsAssignableFrom(aProperty.PropertyType))
{
var value = (MyGenericProperty) aProperty.GetValue(sourceObject, null);
// Use value
}
If these hints don't help you, please give more details of what you're trying to do.

Can I use the result of a C# method (with an argument) as a default argument of another?

I have a static class with method:
public static class FooUtilities
{
public static FooStruct[] GetFooBar(int foo)
{
var fooStruct = new FooStruct[];
// Connect to SOAP API, collect data to put in fooStruct
...
return fooStruct;
}
}
Now I want to use the result of GetFooBar(int foo) as an argument to another method that uses the results of this method to create new fooItem items, something like:
public static FooItem CreateFooItem(fooResult = GetFooBar(int foo))
{
var fooItem = new FooItem(fooResult[0].value, fooResult[1].value,fooResult[2].value);
...
return fooItem;
}
The way I do it now is to write this:
public static FooItem CreateFooItem(FooStruct[] fooResult)
{
var fooItem = new FooItem(fooResult[0].value, fooResult[1].value,fooResult[2].value);
...
return fooItem;
}
This works, but then I have to call the method like:
FooItem myItem = FooUtilities.CreateFooItem(FooUtilities.GetFooBar(12321));
What I'd like is to be able to call:
FooItem myItem = FooUtilities.CreateFooItem();
And have the argument included implicitly when this method is called.
Is this possible?
You can't do this. From the spec:
A default value must be one of the following types of expressions:
a constant expression;
an expression of the form new ValType(), where ValType is a value type, such as an enum or a struct;
an expression of the form default(ValType), where ValType is a value type.
If you'd tried your CreateFooItem(fooResult = GetFooBar(int foo)) example, you'd have got the compiler error "Default parameter value for 'fooResult' must be a compile-time constant" which is a shorter version of the above.
No, you can only use values that can represented as constant literal values. You can, however, usually make null the default value (switching to Nullable<T> if the parameter is a non-nullable struct), and apply the default manually:
public static FooStruct[] GetFooBar(int? foo = null)
{
int fooVal = foo ?? SomeMethod({some args here});
// ... use fooVal from now on
}
You can't do it by specifying a default parameter value (see #Rawling's answer), but you could create a zero-parameter overload that calls the first:
public static FooItem CreateFooItem()
{
return CreateFooItem(GetFooBar(12321))
}
No, the default parameter value needs to be a compile time constant. But you can do this:
public static FooItem CreateFooItem(FooStruct[] fooResult = null)
{
if(fooResult==null)
{
fooResult = FooUtilities.GetFooBar(12321);
}
...
}
If GetFooBar will produce the same default value everytime, optionally, you can "save" that default value. This might improve performance depending on the use case:
private FooStruct[] defaultValue = null;
public static FooItem CreateFooItem(FooStruct[] fooResult = null)
{
if(fooResult==null)
{
fooResult = defaultValue ?? defaultValue = FooUtilities.GetFooBar(12321);
}
...
}

Treat subclass as its superclass when only a member differs by its type

I have a Variable class and and 3 subclasses: VariableBool, VariableLong and VariableDouble. Each subclass defines only a value member of the type of the suffix.
Now, I need to transfert objects based on these classes over WCF. I have multiple clients registering their variale to a server. Whenever a value changes on one client, it's updated in all other clients.
My question is: is there a way to do:
someVar.Value = anotherVar.Value;
regardless of the type, wihout having to check for type, e.g.:
VariableBool anotherVarBool = anotherVar as VariableBool;
if (anotherVarBool != null) {
(someVar as VariableBool).Value = anotherVar.Value;
}
// check other types...
What am I missing? Is there a patern of some kind? Could I use reflection?
Also, I don't think I can use Generics because of the WCF (I've tried but I could make it work).
Thanks
If you are using mex-generated WCF proxies, then I suspect reflection (or ComponentModel) is indeed the simplest option - something like:
public static void Copy<T>(T source, T destination,
string propertyName) {
PropertyInfo prop = typeof(T).GetProperty(propertyName);
prop.SetValue(destination, prop.GetValue(source, null), null);
}
Or if you want to use it even with the variable types as the base-class:
public static void Copy(object source, object destination,
string propertyName) {
PropertyInfo sourceProp = source.GetType().GetProperty(propertyName);
PropertyInfo destProp = destination.GetType().GetProperty(propertyName);
destProp.SetValue(destination, sourceProp.GetValue(source, null), null);
}
Why don't you to put the Value member in the base class Variable.
In that case,
public void UpdateValue( Variable variable )
{
if( variable != null )
// do something with variable.Value
}
However, if you really want to use inheritance, you need to tell the base class what are the sub types by using KnownType attribute and its method
[DataContract()]
[KnownType( "GetKnownType" )]
public class Variable
{
public object Value;
private static Type[] GetKnownType()
{
// properties
return new []{ typeof(VariableBool),
typeof(VariableLong),
typeof(VariableDouble),};
}
}
[DataContract()]
public class VariableBool : Variable
{
}
[DataContract()]
public class VariableLong : Variable
{
}
[DataContract()]
public class VariableDouble : Variable
{
}

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