C# - Keyword usage virtual+override vs. new

151

Solution 1

The "new" keyword doesn't override, it signifies a new method that has nothing to do with the base class method.

public class Foo
{
     public bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public new bool DoSomething() { return true; }
}

public class Test
{
    public static void Main ()
    {
        Foo test = new Bar ();
        Console.WriteLine (test.DoSomething ());
    }
}

This prints false, if you used override it would have printed true.

(Base code taken from Joseph Daigle)

So, if you are doing real polymorphism you SHOULD ALWAYS OVERRIDE. The only place where you need to use "new" is when the method is not related in any way to the base class version.

Solution 2

I always find things like this more easily understood with pictures:

Again, taking joseph daigle's code,

public class Foo
{
     public /*virtual*/ bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public /*override or new*/ bool DoSomething() { return true; }
}

If you then call the code like this:

Foo a = new Bar();
a.DoSomething();

NOTE: The important thing is that our object is actually a Bar, but we are storing it in a variable of type Foo (this is similar to casting it)

Then the result will be as follows, depending on whether you used virtual/override or new when declaring your classes.

Virtual/Override explanation image

Solution 3

Here's some code to understand the difference in the behavior of virtual and non-virtual methods:

class A
{
    public void foo()
    {
        Console.WriteLine("A::foo()");
    }
    public virtual void bar()
    {
        Console.WriteLine("A::bar()");
    }
}

class B : A
{
    public new void foo()
    {
        Console.WriteLine("B::foo()");
    }
    public override void bar()
    {
        Console.WriteLine("B::bar()");
    }
}

class Program
{
    static int Main(string[] args)
    {
        B b = new B();
        A a = b;
        a.foo(); // Prints A::foo
        b.foo(); // Prints B::foo
        a.bar(); // Prints B::bar
        b.bar(); // Prints B::bar
        return 0;
    }
}

Solution 4

The new keyword actually creates a completely new member that only exists on that specific type.

For instance

public class Foo
{
     public bool DoSomething() { return false; }
}

public class Bar : Foo
{
     public new bool DoSomething() { return true; }
}

The method exists on both types. When you use reflection and get the members of type Bar, you will actually find 2 methods called DoSomething() that look exactly the same. By using new you effectively hide the implementation in the base class, so that when classes derive from Bar (in my example) the method call to base.DoSomething() goes to Bar and not Foo.

Solution 5

Beyond just the technical details, I think using virtual/override communicates a lot of semantic information on the design. When you declare a method virtual, you indicate that you expect that implementing classes may want to provide their own, non-default implementations. Omitting this in a base class, likewise, declares the expectation that the default method ought to suffice for all implementing classes. Similarly, one can use abstract declarations to force implementing classes to provide their own implementation. Again, I think this communicates a lot about how the programmer expects the code to be used. If I were writing both the base and implementing classes and found myself using new I'd seriously rethink the decision not to make the method virtual in the parent and declare my intent specifically.

Share:
151

Related videos on Youtube

Василий Сверчков
Author by

Василий Сверчков

Updated on July 01, 2021

Comments

  • Василий Сверчков
    Василий Сверчков almost 3 years

    I have two problems that I would like to ask about. The webapp should send "somedata" via POST (ajax), then put the returned data from the server into the div. I use jQuery, jQuery mobile and phonegap. So the HTML looks like this:

    <div id="searchingform">
        <form method="post" id="sform">
            <input type="text" name="group" id="somedata" value="" placeholder="Enter SOMEDATA that will be posted to the server"/>
            <div id="buttoncover">
                <input type="button" id="loadbut" value="Load" data-mini="true" onClick="sendPost();">
            </div>
        </form> 
    </div>
    <div id="cnt"></div>
    <div id="output"></div>
    

    And here is JS code:

    function sendPost() {
        $.ajax({
            type:'post',
            url:'http://thepagethatanswers.com',
            data:{'group':$('[name=somedata]').val()},
            response:'html',
            success:function (data) {
                $('#cnt').html(data);
            },
            error: function(){
            $('#output').html('Error');
            }
        });
    };
    

    So the user fills the form, presses the button, it is sent to the server, and the answer is filled into #cnt div. Genegally it works BUT:

    1.After pressing the button it remains pressed. It works, but has the appearance of pressed button. jQuery makes that

    <div data-corners="true" data-shadow="true" data-iconshadow="true" data-wrapperels="span" data-theme="b" data-mini="true" data-disabled="false" class="ui-btn ui-shadow ui-btn-corner-all ui-mini ui-btn-up-b" aria-disabled="false">
        <span class="ui-btn-inner">
            <span class="ui-btn-text">Load</span>
        </span>
        <input type="button" id="loadbut" value="Load" data-mini="true" onclick="sendPost();return true;" class="ui-btn-hidden" data-disabled="false">
    </div>
    

    from

    <input type="button" id="loadbut" value="Load" data-mini="true" onClick="sendPost();">
    

    I tried to .removeclass('ui-btn-active') that appears, but it has no effect. I tried to totally rewrite the button, it made it look like inactive, but then it didn't wand to appear like pushed one. I just need it to be able to show normal behavior in terms of appearance.

    2.There is need to resend the 'somedata' from the form to server in order to update the information and load it in the #cnt. And here is my second issue: untill the 'somedata' in the form is not changed to some other value the POST does not happen. Example: we put "1" in the input, press the button, get the answer, it t fills the #cnt - that's fine. Then we press the button again in order to update the info and nothing happens. Change the value of input, press the button - it updates the #cnt according to a new value of input. I need it to be able to press the button many times and it will send the same value and get the right #cnt. The server code is quite complicated, but in fact it just gets the $_POST['somedata'] and then returns html back.

    UPD: Solution to refresh of ajax request: I added to sent data one more variable and now it looks like this:

    data:{'group':$('[name=group]').val(),tstamp: new Date().getTime()}
    

    So the request is sent every time and the data refreshes.

  • Joseph Daigle
    Joseph Daigle over 15 years
    You should revise your code, I had made the methods static (which is valid for using the "new" keyword). But I decided it was clearer to use instance methods.
  • albertein
    albertein over 15 years
    Thank you, i missed the "static" part. Should take more attention on the future
  • odiseh
    odiseh almost 15 years
    Thanks....but could you please explain a little about picture above with regard to the casting you said?
  • odiseh
    odiseh almost 15 years
    Oops If forgot to add these few line to my prev. comment: do you mean virtual/overriding and non-vitual/new are used just for polymorphysm concept and when you simply declare a variable (not using casting) they don't mean? Thanks again.
  • Sully
    Sully over 10 years
    The technical explanations of new vs override are sound, but this answer seems to help the most for guiding devs on which to use.
  • Thomas N
    Thomas N about 9 years
    Note that the line Foo test = new Bar () is crucial here, the new / override keyword for the metods determine which metod is called when you put a Bar into a Foo variable.
  • Don Cheadle
    Don Cheadle about 9 years
    thank you for this - but why use new to "hide" the base method, when simply not using override seems to do the same?
  • Don Cheadle
    Don Cheadle about 9 years
    ... so it's the exact same as simply not having virtual in the base and override in derived? Why does it exist? The code will still run even w/o new - so is it purely just readability?
  • MrSilent
    MrSilent almost 9 years
    Your answer dear sir is pretty vague. new and virtual-override do the pretty same thing, the only difference is that new HIDES the method in the parent class and override.. well, overrides it. Of course it prints false because your test object is of type Foo, if it would be of type Bar, it would print true. Pretty tricky example, though.
  • mr5
    mr5 about 7 years
    new keyword on a member field declaration doesn't make much sense to me. I could still call base.Whatever in the function body
  • mr5
    mr5 about 7 years
    I don't think it was created to prevent the base class from being overriden. I think it was created to avoid name clashing as you can't override a method which is not virtual and the compiler will complain if it sees the same function name on a class "bloodline" with no virtual signature
  • Suncat2000
    Suncat2000 over 3 years
    The compiler won't let you use override here. There is no virtual method available.
  • Tom Yan
    Tom Yan over 3 years
    This is a really nice answer. So new basically allows the parent method to remain accessible (when the child is cast/used as the parent type). On the contrary, virtual+override guarantees that the child method is used regardless of how the child is cast/used (only if overriding, of course).