Tech Off Thread

11 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

Determining if an object inherits a certain base class?

Back to Forum: Tech Off
  • User profile image
    W3bbo

    Probably a very stupid question, but consider this example.

    I've got a control "Foo" that has a control collection. Some of the child controls inherit from a "BaseBar" class. I want to remove all controls that inherit BaseBar.

    I need something like this:


    foreach(Control C in Foo.Controls) {
       
        if(C inherits BaseBar) {
           Foo.Controls.Remove(C);
        }
       
    }


    ...but I'm not aware of any "inherits" operator. Any suggestions?

  • User profile image
    dahat

    foreach(Control C in Foo.Controls) {
       
        if(C is BaseBar) {
           Foo.Controls.Remove(C);
        }
       
    }

    It should be said though that removing items from a list you are iterating through is generally not the best idea.

  • User profile image
    W3bbo

    dahat wrote:
    foreach(Control C in Foo.Controls) {
       
        if(C is BaseBar) {
           Foo.Controls.Remove(C);
        }
       
    }

    It should be said though that removing items from a list you are iterating through is generally not the best idea.


    Thanks, although following your suggestion made over MSNIM I had this:

                foreach(Control C in Controls) {
                   
                    BaseControl B = C as BaseControl;
                    if(B != null) {
                        Controls.Remove( B );
                    }
                   
                }

    But anyway, I just discovered you're right about it being a bad idea, this exception gets thrown:

    The list that this enumerator is bound to has been modified. An enumerator can only be used if the list doesn't change.


    ...are there any other ways to prevent an ASP.NET control from rendering?

  • User profile image
    shooter666

    I haven't exactly tested this, but this should work to remove controls at runtime:

    for(int i = Foo.Controls.Count-1;i > -1;i--)
    {
        if (Foo.Controls[i] is BasePage)
        {
            Foo.Controls.RemoveAt(i);
        }
    }


    this way you loop through the control list top to bottom, that way the enumeration wouldn't screw up...

  • User profile image
    Sven Groot

    W3bbo wrote:

                foreach(Control C in Controls) {
                   
                    BaseControl B = C as BaseControl;
                    if(B != null) {
                        Controls.Remove( B );
                    }
                   
                }

    But anyway, I just discovered you're right about it being a bad idea, this exception gets thrown:

    The list that this enumerator is bound to has been modified. An enumerator can only be used if the list doesn't change.


    Although you don't need it anymore, for future reference I want to add that this can be easily achieved if you don't use foreach but a regular for loop:
    for( int x = 0; x < Controls.Count; ++x )
    {
       Control C = Controls[x];
       BaseControl B = C as BaseControl;
       if( B != null )
       {
          Controls.RemoveAt(x);
          --x;
       }
    }

  • User profile image
    W3bbo

    update:

    Huzzah, I think I've solved it.

    Despite myself authoring dozens of ASP.NET controls, I always thought the .Visible property had to be handled by the overridden .Render() method. But now (after what? about a year?) I realise that ASP.NET handles's the .Visible property and then decides to call .Render().

    foreach(Control C in Page.Controls) {
        
        if(C is W3bcontrol) {
            C.Visible = false;
        }
        
    }
    

  • User profile image
    NolanEgly

    This is a minor point, Sven, but you can avoid modifying the loop index inside the loop if you use a while loop instead.

    int i = 0;
    while( i < Controls.Count )
    {
      Control C = Controls[i];
      BaseControl B = C as BaseControl;
      if( B != null )
        Controls.RemoveAt(i);
      else
        i++;
    }

  • User profile image
    W3bbo

    What's the point though?

    "foreach" is just a shorthand way of doing:

    for(int i=0;i<collection.count;i++){
        <type> foo = (<type>)collection[i];
         %code%
    }


    and "for" (with typical incremeter) itself is shorthand for:

    while(int i < collection.count) {
        %code%
        i++;
    }


    which itself is shorthand for:

    int i = initialiser;
    LoopStart:
    %code%
    if(i < collection.count) {
          goto LoopStart;
    }


    ...which is short for some esoteric processor-specific assembly code which I don't know.


  • User profile image
    PerfectPhase

    No, foreach uses GetEnumerator() which looks very different down at the IL level.

  • User profile image
    W3bbo

    PerfectPhase wrote:
    No, foreach uses GetEnumerator() which looks very different down at the IL level.


    Oh, ah well Smiley

    BTW, PerfectPhase: I added you to my MSN Messenger list last night, you're "stephan@perfectNOSPAMphase.com", right?

  • User profile image
    Sven Groot

    W3bbo wrote:
    PerfectPhase wrote: No, foreach uses GetEnumerator() which looks very different down at the IL level.


    Oh, ah well Smiley

    You can also do foreach enumerations over everything that implements IEnumerable. It doesn't even need to have an indexer (Item property).

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.