Cannot access member of a class through object reference - c#

The following code executes without error and prints "In some", which means that the statement
m[0].Invoke(o, args);
invokes the function some which is a member of the foo class, on object o and affects its public variable i. But when we uncomment the last line of the code and try to compile it, it produces an error. Why??
using System;
using System.Reflection;
class foo
{
public int i;
public foo(int ii = 0)
{
i = ii;
}
public void some(int ii)
{
i = ii;
Console.WriteLine("In some ");
}
}
class main
{
static public void Main()
{
foo f = new foo();
object o = new foo();
Type t = typeof(foo);
object[] args = new object[1];
args[0] = 9;
MethodInfo[] m = t.GetMethods();
m[0].Invoke(o, args);
//Console.WriteLine(o.i);
}
}

But when we uncomment the last line of the code and try to compile it, it produces an error. Why??
Because you've declared o as System.Object, which doesn't have a variable i defined on it as far as the compiler is concerned. You'd need to either cast it to the known type, or use reflection to retrieve this value.
For example:
// You can cast here, since you know the type
foo oAsFoo = o as foo;
Console.WriteLine(oAsFoo.i);
Alternatively, use reflection to get the value:
FieldInfo field = t.GetField("i");
Console.WriteLine(field.GetValue(o));

You need to cast the o too foo in order to execute it.
Console.WriteLine(((foo)o).i)
C# is a statically typed (typed safe) language and only allows type
safe operations and as there is no public member i of class
object therefore it is not allowed by the compiler.

o is of type object which can hold object of any type but instance of object can not access the attributes of assigned class object.
Type casting to its respective class make the public members accessible like this.
Console.WriteLine(((foo)o).i)

Related

error "does not contain a definition for 'getProperty'" when trying to set property of generic typed object

void myFunc<M>()
{
dynamic uploadReq = (M)Activator.CreateInstance(typeof(M));
uploadReq.getProperty("Credentials").SetValue(null);
}
I have a function where I supply a type, an object of this type is created, and then a property on the object is set to null. I get an error
MyCustomType does not contain a definition for 'getProperty'
How can I fix this?
GetProperty its method of Type. Object has no it.
You can use this way:
call GetProperty from type
set value to object
public static void myFunc<M>()
{
dynamic uploadReq = (M)Activator.CreateInstance(typeof(M));
typeof(M).GetProperty("Credentials").SetValue(uploadReq, null);
}
In this specific snippet of code you don't need dynamic or reflection, because you know the type at compile time, just use the generic version of the CreateInstance method or even better the constructor of the type. This is faster and also provides compile time checks.
void myFunc<M>() where M : new()
{
M uploadReq = new M();
uploadReq.Credentials = null;
}
or
M uploadReq = Activator.CreateInstance<M>();
uploadReq.Credentials = null;

C#: What does it mean to use a variable like a type?

I'm new to C#, coming from a Javascript background (so 'typing' is quite new to me).
What does the warning "... is a variable but is used like a type" mean?
I have the following code within a static function called test:
var activeCell = new ExcelReference(1, 1);
Type type = typeof(activeCell);
You can use typeof only with a type, for example Type type = typeof(ExcelReference);
If you want to know what type is this variable use Type type = activeCell.GetType();
Quite easy in fact.
typeof is used with a Class, Interface etc name, meanwhile for what you want you will need the GetType function.
Example :
public class MyObject
{
public static Type GetMyObjectClassType()
{
return typeof(MyObject);
}
public static Type GetMyObjectInstanceType(MyObject someObject)
{
return someObject.GetType();
}
public static Type GetAnyClassType<GenericClass>()
{
return typeof(GenericClass);
}
public static Type GetAnyObjectInstanceType(object someObject)
{
return someObject.GetType();
}
public void Demo()
{
var someObject = new MyObject();
Console.WriteLine(GetMyObjectClassType()); // will write the type of the class MyObject
Console.WriteLine(GetMyObjectInstanceType(someObject)); // will write the type of your instance of MyObject called someObject
Console.WriteLine(GetAnyClassType<MyObject>()); // will write the type of any given class, here MyObject
Console.WriteLine(GetAnyClassType<System.Windows.Application>()); // will write the type of any given class, here System.Windows.Application
Console.WriteLine(GetAnyObjectInstanceType("test")); // will write the type of any given instance, here some string called "test"
Console.WriteLine(GetAnyObjectInstanceType(someObject)); // will write the type of any given instance, here your instance of MyObject called someObject
}
}

Passing generic into a class constructor list

I have a class that takes a generic as a parameter like this
public MyNewClass(string text, T myClass, int f, bool test = false)
The compiler is complaining about T myClass.
I know I can pass "defined" generic classes to a class constructor (such as List, Dictionary etc) and have seen that this can be done in C# as well, but can't find a reference to it.
You should declare the generic parameter, when you declare your class.
public class MyNewClass<T>
{
}
Then this parameter could be accessible from any of the class's methods. When you will create an instance of your MyNewClass, you should define also the type of T, for instance:
var instanceOfMyNewClass = new MyNewClass<className>(text, classIntance, f, true);
where classInstance is an instance of an object of type className.
A good introduction about generics is here.
I suspect that the issue you are facing is that the following does not compile
public class Foo<T>
{
public Foo(string s, T t) { }
}
var foo = new Foo("Hello", new Something());
The fix to this is to specify in the constructor.
var foo = new Foo<Something>("Hello", new Something());
However, this still seems a little strange given that normally, the C# compiler can infer the type of T.
The problem here is that the C# compiler is only allowed to infer generics on the first parameter of a method. So the following IS allowed.
public class Foo<T>
{
public Foo(T t, string s) { }
}
var foo = new Foo(new Something(), "Hello");

Array of objects - modyfing object's fields C#

I've got such a problem. I'm a beginner in C#.
I have an object array (various classes) and in one place of application I want to modify fields like an age or name. Construction
static Object[] prac = new Object[10];
public static void Main(string[] args)
{
prac[0].age = 21;
}
shouts an error
'object' does not contain a definition for 'age' and no extension method 'age' accepting a first argument of type 'object' could be found
I thought that will be similiar to a Java code, but it isn't. What am I doing wrong?
Regards.
You need to cast your member to the class type that contains the age. I'll just assume that your class name is Person and that is has a age member :
static Object[] prac = new Object[10];
public static void Main(string[] args)
{
((Person)prac[0]).age = 21;
}
Important to note are the brackets : (Person)prac[0] is the cast part, you cast the Object prac[0] to a Person object. The outer brackets ((Person)prac[0]) are there so that the code is taken as a Person object, instead of a regular Object.
First you need to cast the object to the type you're intending to work with.
If you work with type object, it has only a limited amount of properties and methods. To use property age, you first need to cast it to the corresponding type that has that property. For instance something like this:
static Object[] prac = new Object[10];
public static void Main(string[] args)
{
SpecificType myObject = prac[0] as SpecificType; // returns null if not successful
if (myObject != null)
myObject.age = 21;
}
HOWEVER, I'm not convinced you're doing the right thing here. I'd personally avoid type object unless absolutely there would be no other way of doing it (and that is very rare in my code). C# is a strongly-type language and by using object you're prone to errors all over the place.
Object doesn't have property age.
All Object's properties and methods are stated here.
It's an array of objects and as the error message suggests, 'object' does not contain a definition for 'age'
You need to declare your array with the type that has age field or property.And the you can modify it whatever you want. For example:
class Person
{
public string Name { get; set; }
}
You have to use an array of your class instead of Object which is the base type of all classes.
static MyClass[] prac = new MyClass[10];
or you have to cast it:
MyClass mc = (MyClass) prac[0];
mc.age = 21;
Object is the base class for all classes in .Net.
Just cast the required value to the required typed class. Or Create a list with the right type instead of object.

Typecast to a type from just the string representation of the type name

sTypeName = ... //do some string stuff here to get the name of the type
/*
The Assembly.CreateInstance function returns a type
of System.object. I want to type cast it to
the type whose name is sTypeName.
assembly.CreateInstance(sTypeName)
So, in effect I want to do something like:
*/
assembly.CreateInstance(sTypeName) as Type.GetType(sTypeName);
How do I do that? And, what do I take on the left side of the assignment expression, assuming this is C# 2.0. I don't have the var keyword.
Usually you let all classes, you want to instantiate this dynamically, implement a common interface, lets say IMyInterface. You can create an instance from the classname string like this:
Assembly asm = Assembly.GetExecutingAssembly();
string classname = "MyNamespace.MyClass";
Type classtype = asm.GetType(classname);
// Constructor without parameters
IMyInterface instance = (IMyInterface)Activator.CreateInstance(classtype);
// With parameters (eg. first: string, second: int):
IMyInterface instance = (IMyInterface)Activator.CreateInstance(classtype,
new object[]{
(object)"param1",
(object)5
});
Even if you dont have a common interface, but know the name of the method (as string) you can invoke your methods like this (very similar for properties, event and so on):
object instance = Activator.CreateInstance(classtype);
int result = (int)classtype.GetMethod("TwoTimes").Invoke(instance,
new object[] { 15 });
// result = 30
The example class:
namespace MyNamespace
{
public class MyClass
{
public MyClass(string s, int i) { }
public int TwoTimes(int i)
{
return i * 2;
}
}
}
Unfortunately there's no way in .NET to do what you want.
Possible partial solutions are:
If you know the type at compile-time (unlikely, since you're creating it at run-time from a string) then simply cast to that type:
YourType t = (YourType)Activator.CreateInstance(sTypeName);
If you know that all the possible types will implement a specific, common interface then you can cast to that interface instead:
IYourInterface i = (IYourInterface)Activator.CreateInstance(sTypeName);
If you can't do either of the above then, unfortunately, you're stuck with object and reflection.
.
Define a generic method in your class, and then you can cast like this:
public T Cast<T>(object obj)
{
return (T) obj;
}
string sTypename = "SomeClassName";
MethodInfo cast = this.GetType().GetMethod("Cast");
MethodInfo genericCast = cast.MakeGenericMethod(new Type[] { Type.GetType(sTypename) });
Object castedValue = genericCast.Invoke(this, new object[] { instanceToBeCasted });
But then I think, what is the point of such casting if you cannot store the casted value in a variable of the actual type, precisely because you don't know the actual type at the time of writing the code?

Categories

Resources