C# - Keyword usage virtual+override vs. new
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.
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.
Related videos on Youtube
Василий Сверчков
Updated on July 01, 2021Comments
-
Василий Сверчков 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.-
AminM almost 11 yearsMSDN say "Using
new
creates a new member with the same name and causes the original member to become hidden, whileoverride
extends the implementation for an inherited member" -
Admin almost 11 years
-
dayuloli about 10 years
-
-
Joseph Daigle over 15 yearsYou 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 over 15 yearsThank you, i missed the "static" part. Should take more attention on the future
-
odiseh almost 15 yearsThanks....but could you please explain a little about picture above with regard to the casting you said?
-
odiseh almost 15 yearsOops 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 over 10 yearsThe 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 about 9 yearsNote 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 about 9 yearsthank you for this - but why use
new
to "hide" the base method, when simply not using override seems to do the same? -
Don Cheadle about 9 years... so it's the exact same as simply not having
virtual
in the base andoverride
in derived? Why does it exist? The code will still run even w/onew
- so is it purely just readability? -
MrSilent almost 9 yearsYour 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 about 7 years
new
keyword on a member field declaration doesn't make much sense to me. I could still callbase.Whatever
in the function body -
mr5 about 7 yearsI 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 novirtual
signature -
Suncat2000 over 3 yearsThe compiler won't let you use
override
here. There is novirtual
method available. -
Tom Yan over 3 yearsThis 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).