C # accessing class members after casting
I've been working with C # and XAML and was wondering if there is a better way to access class members after casting them. This is an example of what I would normally do:
private void MyButton_Clicked(object sender, RoutedEventtArgs e)
{
((PlaneProjection)((Button)sender).Projection).RotationX = 20;
}
Which rotated the button every time you pressed it, but with more complicated actions, I would need more and more parentheses. I know I can use something that made it a little easier to read, but this would still do it:
((sender as Button).Projection as PlaneProjection).RotationX = 20;
There are more parentheses than we would like.
Am I doing this a long way or am I missing something? Or is it the way it is and I have to deal with the possibility of harder reading code like this?
source to share
(A) Strictly speaking, no, there is no way. Once you've done the cast , you're left with a different type of temporary meaning - and almost no syntax branches are left after the cast, whether it's a regular cast or an AS statement. You must either enclose it in brackets, use it right away, or store it in a variable.
(B) Speaking loosely, there is a way: just don't throw at all. But keep in mind that this will be:
- a new .NET platform is required.
- be less secure (compile-time name checking is disabled)
- be even less secure (TYPE checks at runtime are disabled, if a property name is found then it is used regardless of what type of obejct you had in the variable)
- has slightly worse performance (just dynamic statements are slower than compiled ones)
and as i said dynamic, it uses CLR4.0 dynamic expression:
private void MyButton_Clicked(object sender, RoutedEventtArgs e)
{
dynamic tmp = sender;
tmp.Projection.RotationX = 20;
}
But, I really don't suggest doing it just to skip some parentheses. This expression contains a type check ZERO. It is 100% duck. This is fine for a button, as the button API is unlikely to change. But for your own code, which mutates frequently, be careful - or include correct unit tests for the property to exist.
source to share
var button = sender as Button;
if (button == null)
return;
var projection = button.Projection as PlaneProjection;
if (projection == null)
return;
projection.RotationX = 20;
is a much safer way as you make sure your casts don't throw a NullReferenceException.
However, I should mention that it is better to create a ViewModel that contains Double X {get;set;}
and Command
that the button can bind to, and not manipulate the UI elements in code.
source to share