There is a big difference. I suggest you read this and carefully go through the examples.
To summarize, what you're dealing with is the difference between method overriding vs method hiding.
Method overriding allows a base type to access the behavior of the derived type's overridden functionality. This is what you're doing when you use the override
keyword on a derived type's method where the base type's method is marked with the virtual
keyword. On the other hand, using the same method signature on a more derived where the base type's method is not marked as virtual
is what's known as method hiding. You can actually do this without using the new
keyword, but you will get a compiler warning.
Method hiding loses the polymorphic benefits that method overriding provides, in that the methods of the derived class will use the "new" behavior of the hidden method, but base class will continue to use the base class's version of the method. The results of method hiding can seem pretty unintuitive and typically the effects are undesirable in OOP, but it does have its place. For instance, one of my favorite uses of method hiding is to allow for easier unit testing of protected methods.
The following code example is taken directly from the first link and succinctly illustrates one of the ways which method overriding differs from method hiding:
class Program
{
static void Main(string[] args)
{
BaseClass bc = new BaseClass();
DerivedClass dc = new DerivedClass();
BaseClass bcdc = new DerivedClass();
// The following two calls do what you would expect. They call
// the methods that are defined in BaseClass.
bc.Method1();
bc.Method2();
// Output:
// Base - Method1
// Base - Method2
// The following two calls do what you would expect. They call
// the methods that are defined in DerivedClass.
dc.Method1();
dc.Method2();
// Output:
// Derived - Method1
// Derived - Method2
// The following two calls produce different results, depending
// on whether override (Method1) or new (Method2) is used.
bcdc.Method1();
bcdc.Method2();
// Output:
// Derived - Method1
// Base - Method2
}
}
class BaseClass
{
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
public virtual void Method2()
{
Console.WriteLine("Base - Method2");
}
}
class DerivedClass : BaseClass
{
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
}