0

In winforms I want to cast a UserControl as a specific user control so I have access to its public members.

My setup is something like this:

enum ePage
{
    Setup,
    AddMorePagesHere
}

var _pages = new List<UserControl>();

protected override void OnLoad(EventArgs e)
{
    _pages.Add(new ucSetup());
    _pages.Add(new ucAddMorePagesHere());
    base.OnLoad(e);
}

Now is there a difference between

(_pages[(int)ePage.Setup] as ucSetup).SetupMethod();

and

((ucSetup)_pages[(int)ePage.Setup]).SetupMethod();

How would you do it?

Daltons
  • 2,671
  • 2
  • 18
  • 24
  • In terms of functionality, as long as the control isn't null, there's really no difference. If the control _is_ null, you'll get an exception anyways on the call to `SetupMethod`. Stylistically it's up to you. – helrich Apr 09 '15 at 11:46
  • 2
    possible duplicate of [Direct casting vs 'as' operator?](http://stackoverflow.com/questions/132445/direct-casting-vs-as-operator) – James Apr 09 '15 at 11:46
  • If the object isn't a `ucSetup` the difference would be the exception. It would be a null reference exception for the first one and a cast exception for the second. But why don't you just create a field for each control instead of putting them into a list? – juharr Apr 09 '15 at 11:53

3 Answers3

2

"As" cast

(_pages[(int)ePage.Setup] as usSetup).SetupMethod();

If _pages[(int)ePage.Setup] is not usSetup, you will get NullReferenceException here, because (_pages[(int)ePage.Setup] as usSetup) will return null.

Direct cast

((ucSetup)_pages[(int)ePage.Setup]).SetupMethod();

If _pages[(int)ePage.Setup] is not usSetup, you will get InvalidCastException here.

Other than that, no differences.

By the way, I encourage you to follow .NET naming guidelines. Your classes should be named UCSetup (or UcSetup) and UCAddMorePagesHere (or UcAddMorePagesHere).

Alternative

You can simplify your code if you do the following:

public abstract class SetupPage : UserControl
{
    public abstract void SetupMethod();
}  

public class UcSetup : SetupPage
{
    public override void SetupMethod()
    {
        // Do something here
    }
}

public class UcAddMorePagesHere : SetupPage
{
    public override void SetupMethod()
    {
         // Do something here
    }
}

Then, instead of keeping list of UserControl's, keep list of SetupPage's

var _pages = new List<SetupPage>();

You will be able to call your method without a cast:

_pages[(int)ePage.Setup].SetupMethod();
Community
  • 1
  • 1
Spook
  • 25,318
  • 18
  • 90
  • 167
  • Oh, user control inheritance... I'd actually not create a base control, but an interface `ISetupPage` and have that implemented. But as far as I understand the OP, not all the user controls actually contain the `SetupMethod` method. – Thorsten Dittmar Apr 09 '15 at 11:55
  • I already have an interface like @Thorsten Dittmar suggest and `SetupMethod` is unique to a single user control. – Daltons Apr 09 '15 at 12:03
1

There is no functional difference between two lines of code you've shown.

But first one gives you little more flexibility and ability to check if _pages[(int)ePage.Setup] is usSetup to prevent NullReferenceException.

Like this:

var x = _pages[(int)ePage.Setup] as usSetup;
if (x != null)
    x.SetupMethod();

In your second case you can't do such a check and it will be cast exception if _pages[(int)ePage.Setup] has type incompatible with usSetup.

Andrey Korneyev
  • 26,353
  • 15
  • 70
  • 71
1

The difference that matters to you is that:

(_pages[(int)ePage.Setup] as usSetup).SetupMethod();

might throw a NullReferenceException if the control you're casting is not usSetup, as the as operator then returns null.

while the

((ucSetup)_pages[(int)ePage.Setup]).SetupMethod(); 

might throw an InvalidCastException.

As long as you're sure that you're casting the right object, you're safe to use either.

Actually, I'd ensure that there's really only one control per ePage value, so I'd use a dictionary instead of a list:

Dictionary<ePage, UserControl> pages = new ...;
pages[ePage.Setup] = new usSetup();
pages[ePage.Other] = new ...;

var page = pages[ePage.Setup] as usSetup;
...
Thorsten Dittmar
  • 55,956
  • 8
  • 91
  • 139