C# access to stack object property - c#

How can I access the objects property in this situation?
Araba araba = new Araba();
araba.Renk = "mavi";
araba.fiyat = 12345;
// I created this class and it working normally
ArrayTypedStack asd = new ArrayTypedStack(10);
asd.Push(araba);
object araba2 = asd.Pop();
araba2. //cant access

Here you are assigning the value of asd.Pop() to a variable of the type object.
object is the root of all objects (all objects inherit from it and can be casted to it) and as such has no real information about what it is. It's just like any object in real life is a thing.
The solution here is to declare the araba2 as the type Araba, that will give you access to all the properties on the next line.
I don't know the implementation of the ArrayTypedStack and what the Pop() method looks like (it's return type) so it's possible that this will give you an error, saying that it can't convert an object to the type Araba. This is the type safety implemented in .NET. You have to convince .NET that it's of the type Araba, this can be by casting
Araba araba2 = (Araba)asd.Pop();
this can still give an error on runtime if the object returned from Pop() isn't of the type Araba, in this case you can ask .NET to try to cast it, there are serveral options for this:
object popResult = asd.Pop();
if (popResult is Araba) {
Araba araba2 = (Araba)popResult;
}
// can be written as follows:
if (popResult is Araba araba3) {
araba3.fiyat = 65432;
}
// can also be done as follows
Araba araba4 = asd.Pop() as Araba;
if (araba4 != null) {
araba4.fiyat = 84368;
}

Well, your araba2 variable is of type object. Thus, regardless of the actual type of the instance it contains, through the object variable araba2 you can only access members that are provided by the type object.
To access members provided by the Araba type (and assuming the instance in the araba2 variable is an instance of type Araba), the araba2 variable itself should be of type Araba, or the value of araba2 needs to be cast as Araba.
Thus,
var araba2 = asd.Pop();
or
var araba2 = (Araba) asd.Pop();
with the first example code line above requiring that the return type of the Pop method is Araba (or a type derived from Araba). The latter code line example will work regardless of the return type of Pop as long as the value returned by Pop is an actual Araba instance (or is something that is convertible to an Araba instance).

Related

PropertyInfo.GetValue(null) - how it should behave?

I'm writing a compare properties two objects of some class, for further listing differences.
Class oldObj, newObj;
//some initiation of above
Class classObject = new Class();
var objectKeys = classObject .GetType().GetProperties().ToList();
objectKeys.ForEach(key => {
var previousKeyValue = key.GetValue(oldObj);
var newKeyValue = key.GetValue(newObj);
if (!Equals) {...}
});
In special cases, newObj or oldObj can be nulls.
My problem is that, in such a case: key.GetValue(null) I'm getting CS0120 exception - "Non-static method requires a target".
Looking at PropertyInfo options (from metadata):
public object? GetValue(object? obj);
I assumed that it will be able to handle such a situation with object being null, with e.g. return null as its value.
Could you please explain if this is proper behaviour of this code, or I'm making something wrong to use null?
In such a case I would probably just before ForEach make some verification if objects are nulls and write separate compare code, handling this situation.
You are misunderstanding the nature of the parameter that is passed to GetValue().
When you pass in an object reference, it means that the reference is an instance property on an instance of an object. If you omit the object reference, you are telling the reflection api that you are trying to access a static member.

Get the actual type from a Type variable

I am trying to get a type from a Type variable. For example:
Type t = typeof(String);
var result = SomeGenericMethod<t>();
An error happens on the second line, because t is not a type, it's a variable. Any way to make it a type?
To make an instance of a generic based on a Type, you can use reflection to get an instance of the generic with the type you want to use, then use Activator to create that instance:
Type t = typeof (string); //the type within our generic
//the type of the generic, without type arguments
Type listType = typeof (List<>);
//the type of the generic with the type arguments added
Type generictype = listType.MakeGenericType(t);
//creates an instance of the generic with the type arguments.
var x = Activator.CreateInstance(generictype);
Note that x here will be an object. To call functions on it, such as .Sort(), you'd have to make it a dynamic.
Please Note that this code is hard to read, write, maintain, reason about, understand, or love. If you have any alternatives to needing to use this sort of structure, explore those thoroughly.
Edit: You can also cast the object you receive from the Activator, such as (IList)Activator.CreateInstance(genericType). This will give you some functionality without having to resort to dynamics.
No, you cannot know the value of a Type object at compile time, which is what you would need to do in order to use a Type object as an actual type. Whatever you're doing that needs to use that Type will need to do so dynamically, and not require having a type known at compile time.
An ugly workaround using reflection:
Class with generic Method
public class Dummy {
public string WhatEver<T>() {
return "Hello";
}
}
Usage
var d = new Dummy();
Type t = typeof(string);
var result = typeof(Dummy).GetMethod("WhatEver").MakeGenericMethod(t).Invoke(d, null);
On class instantiation see Max's solution

How to use the type 'Type'

I know that I can use the type string as:
string someString = "This is my string";
I am not sure how to use the type Type
Type someType = someString.GetType();
How could I create a variable based on that type. I want to do something like
someType someOtherString = "here is another string";
//string
In other words, how could I create a variable based on some type?
There are a few ways to go about this, but the simplest would be to use the Activator class.
http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx
Example:
Type t = someClassInstance.GetType();
object o = Activator.CreateInstance(t);
Variable types have to be known at declaration time. You can declare a variable of type object and then dynamically create an instance of a type which you only know about at execution time, but you can't dynamically declare a variable like that.
The closest you could get would be to create a generic type and instantiate that using a type argument specified with reflection. Then you really would have a variable of the right type - but you wouldn't be able to do anything particularly useful with it.
It's important to distinguish between the type of a variable and the type of the object a variable's value may refer to. For example:
object foo = Activator.CreateInstance(someType);
will end up with a variable of type object, but the value of foo will be a reference to an instance of whatever type someType refers to.
Try
var object = Activator.CreateInstance(myType);
Starting from C# 3 you can do:
var someOtherString = "here is another string";
This way you don't care what's the type, var is type "joker" and save you the need to know the type at declaration time.
Hope that's what you mean?
use Assembly.CreateInstance()
Type type = typeof(String);
Assembly asm = Assembly.GetExecutingAssembly();
object blah = asm.CreateInstance(type.FullName);

Creating an instance of variable with reflection

I want to create an instance of type t with reflection, that is
Type t = typeof(string);
string s = (t)Activator.CreateInstance(t); // this fails because of convertion
string s = Activator.CreateInstance(t) as t // also fails
Is there a way to perform such a convertion?
Thanks.
Yes. You have to convert to string, not to t. You may want a generic method, alternatively:
public T GetInstance<T>()
{
Type t = typeof(T);
T s = (T)Activator.CreateIstance(t);
return s;
}
As things stand you are attempting to cast an object that is actually an instance of System.String to type System.Type...
Try this:
string s = (string)Activator.CreateInstance(t);
Activator.CreateInstance returns an instance boxed in an object so it must be cast to the correct type before you can use it.
In your example t is a Type object variable and not a type reference. You must either specify the type directly as in my example or you can use generics.

How to generate an instance of an unknown type at runtime?

i've got the following in C#:
string typename = "System.Int32";
string value = "4";
theses two strings should be taken to generate an object of the specified type with the specified value...
result should be:
object o = CreateUnknownType(typename, value);
...
Int32 test = (Int32)o;
Is this what are you are thinking?
object result = Convert.ChangeType("4", Type.GetType("System.Int32"));
As stated, this is too broad and can not be solved generally.
Here are some options:
Type type = Type.GetType(typename);
object o = Activator.CreateInstance(type);
This will create an instance of the type that typename is describing. It calls the parameterless constructor of that type. (Downside: Not all objects have a parameterless constructor. Further, this does set the state of the object using value.)
Type type = Type.GetType(typename);
object o = Activator.CreateInstance(type, new[] { value });
This will create an instance of the type that typename is describing. It calls a constructor of that type that accepts one parameter of type string. (Downside: Not all objects have such a constructor. For example, Int32 does not have such a constructor so you will experience a runtime exception.)
Type type = Type.GetType(typename);
object o = Convert.ChangeType(value, type);
This will attempt to convert the string value to an instance of the required type. This can lead to InvalidCastExceptions though. For example, Convert.ChangeType("4", typeof(FileStream)) will obviously fail, as it should.
In fact, this last example (create an instance of type FileStream with its initial state determined by the string "4") shows how absurd the general problem is. There are some constructions/conversions that just can not be done.
You might want to rethink the problem you are trying to solve to avoid this morass.
Creating an instance of a type you know by name (and which should have a default constructor):
string typeName = "System.Int32";
Type type = Type.GetType(type);
object o = Activator.CreateInstance(type);
Parsing a value from a string will obviously only work for a limited set of types. You could
use Convert.ChangeType as suggested
by PhilipW
or maybe create a
Dictionary<Type,Func<string,object>>
which maps known types to known parse
functions
or use reflection to invoke the
Parse(string) method on the type,
assuming there is one:
string valueText = "4";
MethodInfo parseMethod = type.GetMethod("Parse");
object value = parseMethod.Invoke(null, new object[] { valueText });
or maybe you can use the
infrastructure provided by the .NET
component model. You can fetch the
type converter of a component and use
it like this:
TypeConverter converter = TypeDescriptor.GetConverter(type);
object value = converter.ConvertFromString(valueText);
Your logic seems a little flawed here. Obviously, if you're directly casting the object at a later time to the actual type it is, then you must know the type to begin with.
If there's something else that is missing from this question please elaborate and maybe there is a more appropriate answer than simply, "This doesn't make much sense."
Perhaps you have a set of different types, all of which implement a known interface?
For example if you have several different user controls and want to load one of them into a container, each one might implement IMyWobblyControl (a known interface) yet you might not know until runtime which of them to load, possibly from reading strings from some form of configuration file.
In that case, you'll need to use reflection to load the actual type from something like the full assembly name, then cast it into your known type to use it.
Of course, you need to make sure that your code handles invalid cast, assembly not found and any of the other exceptions that are likely to come along through something as wobbly as this...
This seems like a job for Int32.Parse(string). But to agree with the others it seems this is "unique" and one should probably think gloves.
Here's a specific example of the problem involving Azure SQL Federations...which splits data into separate db's according to a key range.
The key range types are:
SQL / .Net SQL type / CLR .Net
INT / SqlInt32 / Int32, Nullable
BIGINT / SqlInt64 / Int64, Nullable
UNIQUEIDENTIFIER / SqlGuid /Guid, Nullable
VARBINARY(n), max n 900 / SqlBytes, SqlBinary /Byte[]
Ideally, a C# function param could take either .Net SQL type or CLR .Net type but settling on just one category of type is fine.
Would an "object" type param be the way to go? And, is there a feasible way to identify the type and convert it accordingly?
The concept is something like:
public void fn(object obj, string fedName, string distName, bool filteringOn)
{
...figure out what type obj is to ensure it is one of the acceptable types...
string key = obj.toString();
return string.Format("USE FEDERATION {0} ({1}='{2}') WITH RESET, FILTERING = {3}", fedName, distName, key, (filteringOn ? "ON" : "OFF"));
}
Though the param value is cast to string, it will be recast/checked on the sql server side so validating it on the app side is desired.
After using:
Type type = Type.GetType(typename);
Try this extension method:
public static class ReflectionExtensions
{
public static T CreateInstance<T>(this Type source, params object[] objects)
where T : class
{
var cons = source.GetConstructor(objects.Select(x => x.GetType()).ToArray());
return cons == null ? null : (T)cons.Invoke(objects);
}
}
Hope this helps.

Categories