In a call back like this:
this.Model.LoadStudent(student_key, (o, a) =>
{
var student = o as Students;
If I put a break point on first line, debugger shows me that "o" has what I am looking for and also shows me its type which is "Students" but as soon as it goes to next line and does the cast, the result is null. Why? What is happening?
You're not casting - you're using the as operator. If you instead actually cast, I suspect you'll get an exception:
var student = (Students) o;
I suspect you've actually got multiple types called Students, and if you really cast instead of using as you'll see the actual type involved.
For example:
using System;
namespace Bad
{
class Students {}
class Test
{
static void Main()
{
object o = new Good.Students();
Students cast = (Students) o;
}
}
}
namespace Good
{
class Students {}
}
This leads to:
Unhandled Exception: System.InvalidCastException:
Unable to cast object of type 'Good.Students' to type 'Bad.Students'.
at Bad.Test.Main()
Note how you get the fully-qualified type names in the exception.
In general, it's a bad idea to use as unless you really expect that the object may not be of the right type, and usually you check for that afterwards. See my blog post on the topic for more details.
In that case your object isn't of the Students type. Casting in this way won't throw an error if you are casting to the wrong type it will just make the object null.
Related
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).
I have an object like this
object tst = folderItems.AsEnumerable().Select(i => new {
i.File.ListItemAllFields.FieldValues,
i.File.UniqueId
});
in this code File.ListItemAllFields.FieldValues is a dictionary. While constructing this object I want to select only few items from this dictionary. And I have tried something like this
object tst = folderItems.AsEnumerable().Select(i => new {
i.File.ListItemAllFields.FieldValues.Where(x=>x.Key=="mykey"),
i.File.UniqueId
});
But this resulted in a compile time error. How can I achieve this?
Error
Invalid anonymous type member declarator. Anonymous type members must be declared with a member assignment, simple name or member access.
Well it simply says that for your anonymous class you should provide a name:
object tst = folderItems.AsEnumerable().Select(i => new {
FieldValues = i.File.ListItemAllFields.FieldValues.Where(x=>x.Key=="mykey"),
i.File.UniqueId
});
Note that if you don't give it a name (like the second property), the property name (UniqueId in this cause will be used), this you know as you have used it like that, however if it is not a property and it's a method, you should give it a name yourself, for example you'll get an error if you don't give a name for something.Count() and it should be Count = something.Count()
The above code should solve your problem. also consider adding ToList(), ...
.Where(x=>x.Key=="mykey").ToList()
Imagine that you want to declare an object with an anonymous type, but you need it to be generic (I can't think of an actual reason why, this is theoretical). How would you create such an object?
For example:
var anonymousGeneric = new <T>{ }; // <- doesn't work
var anonymousGeneric = Activator.CreateInstance((new { }).GetType()); // Not generic
edit:
// because:
(new { }).GetType().IsGenericType == false
// Of course, any useful anonymous object _will_ be generic:
(new { a="b" }).GetType().IsGenericType == true
// But in the process of testing various aspects of this question
// it had never occurred to me that I needed to supply any property
// (this was all theoretical, remember)
end edit
But neither of those works. Of course, the real-world solution to this imagined problem is to define an actual class definition:
public GenericThing<T> { }
But that isn't anonymous like above.
Once the object is created, imagine using it later on with something like:
var anonymousGenericType = anonymousGeneric.GetType();
// These throw exception
// <>f__AnonymousType0#1 is not a GenericTypeDefinition. MakeGenericType may only be called on a type for which Type.IsGenericTypeDefinition is true.
// + System.RuntimeType.MakeGenericType(System.Type[])
var intThing = anonymousGenericType.MakeGenericType(typeof(int));
var stringThing = anonymousGenericType.MakeGenericType(typeof(string));
In summary, is it possible to create an anonymous generic object?
(I can't think of an actual reason why, this is theoretical)
In that case, let's stick with the simple and obvious, since it's easier to find a reason: simply create a regular anonymous object from a generic method.
public object Foo<T>(T t) { return new { t }; }
Here, Foo(0) and Foo("") will necessarily return different types, but they'll still share a type definition.
Pretty much any use of anonymous types can make equal sense inside a generic method.
anonymousGeneric.GetType() is returning the wrong type of generic type: Closed (with type parameter(s)) vs open (without)1. If you want to change a type parameter, you need to get the generic type definition from it.
The following actually works, though I can't imagine what good it does anybody 2:
var anonymousGeneric = new {a = "b"};
var anonymousGenericType = anonymousGeneric.GetType().GetGenericTypeDefinition();
var intThingType = anonymousGenericType.MakeGenericType(typeof(int));
var intThingInstance = Activator.CreateInstance(intThingType, 9);
Now we have a thing just like anonymousGeneric, but its type parameter is int instead of string, and its a property is 9. But what's it good for? How do you declare a reference to it? You could bind to its properties in XAML, if you had some time on your hands.
1 Thanks to Amy and Servy for pitching in to clear up my confusion with terminology.
2 Note that there are more things in heaven and earth than are dreamt of in my philosophy.
I have 2 classes:
class A {
public void A_1(Object b) {
...
Type t = b.GetType();
(t.FullName)b.B_1(); //It doesn`t work! Error in cast
}
....
}
class B {
public void B_1() {
...
}
....
}
A a = new A();
B b = new B();
a.A1(b);
How to cast object correctly?
If you want to cast an object of any type to an object of another type, you do this:
// Will Throw an exception at runtime if it cant be cast.
B newObject = (B)oldObject;
// Will return null at runtime if the object cannot be cast
B newObject = oldObject as B;
// If in a generic method, convert based on the generic type parameter regardless of condition - will throw an exception at runtime if it cant be cast
B newObject = (T)Convert.ChangeType(oldObject, typeof(T))
Your syntax is off; you don't convert from the fullname to the object, you simply convert from the type symbol.
double x = (double)40;
ClassB anotherInstance = (ClassB)someOtherInstance;
What you're trying to do is basically:
Foo myFoo = ("Foo")myObject;
That definitely will not work in C#. When you cast in C#, the compiler emits code that does the cast, it needs to know what it's casting from and to, in order to write that code. A string does not help the compiler out here.
As others have pointed out, what you want to do doesn't seem like you really need to (unless this is just a contrived example). If you really want to do this, you'll need to work with a more dynamic language than C#, or find a C# friendly way of accomplishing this.
Are you sure you didn't mean to do (B)b.B_1()?
C# has a static type-system, i.e. all types must be known at compile-time (modulo reflection). So, casting to a type that is only known at run-time makes no sense. Specify the type explicitly:
public void A_1(object obj)
{
...
B b = (B)obj;
b.B_1();
// or
((B)obj).B_1();
}
You can also do this:
class A {
public void A_1(Object b) {
...
if (b is B)
{
((B)b).B_1();
}
}
....
}
Type.FullName is just a string; it's not a type. Use this instead: ((B)b).B_1(); Also, using GetType() is a way to get the type of an object dynamically, but casting is only possible or useful when the target type is known at compile time (not dynamic at all). In order to cast, simply refer to the type directly in a pair of parentheses. Don't attempt to obtain or use an object of type Type.
Recently I've run into strange issue related to casting. Every discussion/post I've seen tends to revolve around using casting when one is sure about the object being casted plus a couple of details. I haven't however found what's the reasoning behind the code below:
class Program
{
static void Main(string[] args)
{
var h = new SomeCommandHandler();
var c = h as ICommandHandler<ICommand>; //this works as expected
//var c = (ICommandHandler<ICommand>)h; //this throws - why?
}
interface ICommand { }
class SomeCommand : ICommand { }
interface ICommandHandler<I> where I : ICommand { }
class SomeCommandHandler : ICommandHandler<SomeCommand> { }
}
So why the second call throws an exception? What's the difference between casting and as operator that I'm not aware of?
EDIT:
It wpuld throw in the commented line above
"Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'SomeCommandHandler' to type 'ICommandHandler`1[ConsoleApplication1.Program+ICommand]'"
Well, that's the whole entire difference right there. The as operator returns null if the object can't be cast to that type, and just casting produces an exception.
Others have already explained the difference between the direct cast throwing an exception and as returning null when the cast fails. In order to be able to make such a cast succeed you will need to make the generic interface contravariant:
interface ICommandHandler<out I> where I : ICommand { }
However, this might not be possible, depending on how the interface really looks (I am assuming that you are showing a stripped down version for brevity). If your interface contains method that accepts an argument of the type I this will not work; the type I must appear only in get-operations:
interface ICommandHandler<out I> where I : ICommand
{
void SetCommand(I n); // this would not be allowed...
I GetCommand(); // ...but this would.
}
It throws an exception because h is of type SomeCommandHandler which is ICommandHandler<SomeCommand> and you try to cast it to ICommandHandler<ICommand> whis is a different type.
The cast fails because an ICommandHandler<SomeCommand> is not an ICommandHandler<ICommand>. See here for more details & examples.
The as simply returns null when the instance is not of the specified type, whereas the cast throws an InvalidCastexception
the variable c is a is null. It doesn't throw because that's what using "as" means. In other words the instance h is Not an instance of ICommandHandler.
The next line throws because you're attempting to force a cast of an instance of SomCommandHandler to an instance of ICommandHandler
Make sense?