Question

I've been working with C# and XAML and was wondering if there was any better way to access members of a class after casting them. This is an example of what I'd normally end up having to do:

private void MyButton_Clicked(object sender,  RoutedEventtArgs e)
{
    ((PlaneProjection)((Button)sender).Projection).RotationX = 20;
}

Which'd rotate the button every time you clicked it, but with more complex actions I'd need more and more parentheses. I know I can use as which'd make it a little easier to read, but that'd still make it:

((sender as Button).Projection as PlaneProjection).RotationX = 20;

Which is still more parentheses than I'd like to have.

Am I doing this the long way or missing something? Or is this just the way it is and I'll have to deal with the possibility of harder to read code like this?

Was it helpful?

Solution

(A) Speaking strictly, nope, there's no way. After you make a cast, you're left with a temporary value of a different type - and almost no syntax branches are left after the cast, be it normal cast or the AS operator. You must either parenthesize it and immediatelly use it, or you must store it in a variable.

(B) Speaking loosely, there's a way: just do not make the cast at all. But be informed that it will:

  • require the newer .Net platform
  • be less safe (compile time name checks are OFF)
  • be even less safe (runtime TYPE checks are off, if property-name is found then it used, regardless of what exact obejct type you had in the variable)
  • has a bit worse performance (simply, dynamic ops are slower than compiled ones)

well, and as I said dynamic, it uses the 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 parenthesis.. There is ZERO type checking in this expression. It is 100% duck typing. For a Button, it is OK, as the API of the button is really not likely to change. But for your own code which will often mutate, be careful - or include proper unit tests for property existence.

OTHER TIPS

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 since you're making sure your casts won't throw NullReferenceException.

However, I must mention that I would rather create a ViewModel holding the Double X {get;set;} and a Command to which the button can be bound, and not manipulate UI elements in code behind.

If you don't like parenthesis, you can create variables instead.

var button = (Button)sender; // or 'sender as Button'
var planeProjection = (PlaneProjection)button.Projection; // or 'button.Projection as PlaneProjection'

I don't see any way to get reed of the parentheses and casts.

can't you just divide it

var planeProjection = (PlaneProjection)((Button)sender).Projection;

and then

planeProjection.RotationX = 20;
planeProjection.RotationY = 20;
planeProjection.RotationZ = 20;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top