0

Usually, I know what kind of specific control raises a certain event so I can make, inside the event handler, a reference to it by a manual downcast of its sender parameter like this (assuming that sender is a Button):

var refToSender = (Button)sender;

Now, if for any reasons I cannot know the exact type of the sender, is it possible to make an automatic downcast without the necessity of using conditional blocks? In other words, is there the possibility to write something like this:

var refToUnknownSender = (Magic_here)sender;
Clemens
  • 123,504
  • 12
  • 155
  • 268
  • did you tried using `dynamic` ? – rahulaga-msft Mar 30 '18 at 10:48
  • 2
    No. The type of variables is determined at compile-type by the C# compiler (that is what the `var` keyword instructs the C# compiler to do), but the actual concrete type of the sender object is something that is only known at run-time. Perhaps `dynamic` can help you, as Rahul suggested. –  Mar 30 '18 at 10:53
  • if you have senders of different types and the real type of sender matters in handler - maybe you should create a handler for each sender type? – ASh Mar 30 '18 at 11:27
  • 2
    Why do you want to do this at all? If you tell us the exact reason, we might be able to propose a better solution. – Clemens Mar 30 '18 at 11:41

1 Answers1

-1

You can, but I'm struggling to see why you would gain any benefit from that. I'll explain my thinking. In your handler you could do:

Type t = sender.GetType();
var myvar = Convert.ChangeType(sender, t);

myvar is now a button or whatever. Which is all very well until you try and use that in any code. Because if you then try and use something relying on that type like:

string senderName = myvar.Name;

The compiler won't have any of that because it doesn't know what type senderName is so it doesn't know it has a Name property.

I can't see what the point of downcasting in some generic way would be since you do so in order to write code using that type. If you don't know the type then you can't do that.

All this is largely academic to developers using MVVM because any event handlers will probably be in behaviors and you usually already have the type of properties in viewmodels.

Andy
  • 11,864
  • 2
  • 17
  • 20
  • 1
    This is utter nonsense. `sender` obviously is already an object instance of the type returned by `sender.GetType()`. So, the next line `Convert.ChangeType(...)` does exactly nothing (it tries to convert sender to the type it already is). Since the return type of `Convert.ChangeType(...)` is `object`, the type of the variable `myvar` is object - just like the variable/method argument `sender`. So what is the purpose of this rather pointless exercise? –  Mar 30 '18 at 17:31
  • 1
    Wait, what? Your point was to write nonsensical code in your answer? Why? For fun??? If you tried to make a specific point with that, you completely failed. Because somebody who does not understand C#/.NET well will not understand the point you tried to make. And for anybody else knowing a bit about C#/.NET it is just pure nonsense... –  Mar 30 '18 at 17:44
  • No. My point was to show that casting doesn't get you anywhere unless you know what you're casting to in advance. – Andy Mar 30 '18 at 17:46
  • Okay, i see. But there must be a better way to bring this point across without a far-fetched convoluted code example like this... –  Mar 30 '18 at 17:47
  • Feel free to explain that in a clearer manner. Preferably a positive one. – Andy Mar 30 '18 at 17:48
  • Yeah, guilt-tripping does not really work well with me. I know, one of my many weaknesses ;) –  Mar 30 '18 at 17:48
  • We all have our cross to bear. I'm not sure how 3 lines of code are that convoluted though. – Andy Mar 30 '18 at 17:50
  • @elgonzo you are completely wrong. Look [at this LINQPad query](http://share.linqpad.net/ib6qio.linq). You can convert to something other than just object. What would the point of `ChangeType` be if you couldn't? Have you seen the docs? [Returns an object of the specified type and whose value is equivalent to the specified object.](https://msdn.microsoft.com/en-us/library/dtb69x08(v=vs.110).aspx). This is pretty much exactly the answer I would have written had I the time when I saw the question. – Crowcoder Mar 31 '18 at 11:26
  • @Crowcoder, read my first comment. Then look at the code in the answer, then re-read what i wrote in my first comment. Also, if you see the question that is about down**casting** and you think about Convert.ChangeType() being related to casting (it's about conversion, it even says "Convert."), well, um, uh... no, it is not... o.O (Casting could involve implicit/explicit conversion, but conversion is not synonymous with casting) –  Apr 01 '18 at 10:13
  • @elgonzo people don't always use the proper terms in their questions. Here I read "downcast" as convert or whatever else will work to obtain the true type of "sender". I read your first comment enough times. I thought it was unnecessary rude and , I'm sorry, your explanation of changetype is incorrect. – Crowcoder Apr 01 '18 at 10:28
  • @Crowcoder, but the question is correctly termed, and makes it pretty clear that it is about downcasting, not type conversion. It even shows a (pseudo) code sample with a (brief) explanation: Casting the reference to sender (which is a `object` reference to a Button object instance) to a reference/variable of type `Button`, "_assuming that sender is a Button_" (quoted from the question). You read things into the question that are not there at all. It is okay if you think my first comment was rude and you would like to call me out for it, but don't misrepresent the question please. –  Apr 01 '18 at 10:35
  • @elgonzo so you think OP would reject a solution using conversion because it's not a cast? Again, people don't always use the best phrasing and the problem is clearly not specifically casting, it is using the parameter in a meaningful way when you don't know the runtime type. – Crowcoder Apr 01 '18 at 10:48
  • I thought convert.changetype actually casts internally. Which is why you get an invalidcastexception if it fails. But if we're to assume it's always a button then you can just cast to button and the question makes no sense. – Andy Apr 01 '18 at 10:50
  • @Crowcoder, there is no solution to the answer that would require conversion, as the question specifically states that the user want to have a reference to the object where the reference type **is** the actual type of the object. Also, take the time to read the documentation Convert.ChangeType() you linked. It is pointless to use it to **downcast** a base reference (such as a variable of type `object`) to a reference of a derived type (such as a variable of type `Button`), as it returns a reference of type `object`, no matter the actual type of the object returned. –  Apr 01 '18 at 10:53
  • To make it abundandtly clear, the question is not about how to convert an object of type X to another type Y. The object will always be of type X. The question is to get a reference (variable) of the appropriate type (i.e., the type of the object) -- which of course is not possible, as the type of a variable (= reference type) is determined at compile time. Again, no type conversions involved in the question here. So, please stop arguing about type conversions. It is unrelated to the question. –  Apr 01 '18 at 10:58
  • @elgonzo I agree with you there ^. And also that there is no solution, which is why I upvoted the answer that says so. – Crowcoder Apr 01 '18 at 11:02