[ACCEPTED]-Why is overriding static method alowed in C#-static

Accepted answer
Score: 26

The new keyword does not override a method. It 4 instead creates a new method of the same 3 name which is independent of the original. It 2 is not possible to override a static method 1 because they are not virtual

Score: 15

You're not overriding it, you're hiding 19 it. A normal method would exhibit exactly 18 the same behavior so there is nothing specific 17 to static methods here.

Hiding is only useful 16 in a few cases. The one where I came across 15 most often is making the return type more 14 specific in a derived class. But I never 13 had that occur with static methods.

One area 12 where static functions with a certain name 11 might be useful is if you use reflection 10 and want to get information on each class 9 by returning it from a method. But of course 8 in most cases an attribute fits better.

And 7 it's not likely to create bugs since your 6 code produces a compiler-warning:

Warning 5 'StaticHiding.SpecificLogger.LogName' hides 4 inherited member 'StaticHiding.BaseLogger.LogName'. Use 3 the new keyword if hiding was intended.

And 2 if you use new you should know what you're 1 doing.

Score: 12

Others have pointed out that this isn't 112 overriding, but that still leaves your original 111 question: why are you able to do it? (But 110 the question is really "why can you hide 109 static methods".)

It's an inevitable feature 108 of supporting the independent versioning 107 of component that contain base classes 106 and components that use those base classes.

For 105 example, imagine that component CompB contains 104 the base class, and some other component 103 CompD contains a derived class. In version 102 1 of CompB, there might not have been any 101 property called LogName. The author of CompD 100 decides to add a static property called 99 LogName.

The critical thing to understand 98 at this point is that the author of v1 of 97 CompD was not intending to replace or hide 96 any feature of the base class - there was 95 no member called LogName in the base class 94 when they wrote that code.

Now imagine that 93 a new version of the CompB library is released. In 92 this new version, the author added a LogName 91 property. What's supposed to happen in CompD? The 90 options appear to be:

  1. CompD no longer works because the LogName it introduces clashes with the LogName added to CompB
  2. Somehow make the CompD's LogName replace the base CompB LogName. (It's not actually remotely clear how this could work with statics. You could envisage this with non-statics though.)
  3. Treat the two LogName members as being completely different members that happen to have the same name. (In reality, they don't - they're called BaseLogger.LogName and SpecificLogger.LogName. But since in C# we don't always need to qualify the member name with the class, it looks like they're the same name.)

.NET chooses to do 89 3. (And it does that with both statics and 88 non-statics. If you want behaviour 2 - replacement 87 - with non-statics, then the base has to 86 be virtual and the derived class has to mark the method 85 as override to make it clear that they were deliberately 84 overriding a method in the base class. C# will 83 never make a derived class's method replace 82 a base class's method unless the derived 81 class explicitly stated that this is what 80 they wanted.) This is likely to be safe 79 because the two members are unrelated - the 78 base LogName didn't even exist at the point 77 where the derived one was introduced. And 76 this is preferable to simply breaking because 75 the latest version of the base class introduced 74 a new member.

Without this feature, it would 73 be impossible for new versions of the .NET 72 Framework to add new members to existing 71 base classes without that being a breaking 70 change.

You say that the behaviour isn't 69 what you expect. Actually it's exactly what 68 I'd expect, and what you'd probably want 67 in practice. The BaseLogger has no idea 66 that the SpecificLogger has introduced its 65 own LogName property. (There's no mechanism 64 by which it could because you cannot override 63 static methods.) And when the author of 62 SpecificLogger wrote that LogName property, remember 61 that they were writing against v1 of BaseLogger 60 which didn't have a LogName, so they weren't 59 intending that it should replace the base 58 method either. Since neither class wants 57 replacement, clearly replacement would be 56 the wrong thing.

The only scenario in which 55 you should ever end up in this situation 54 is because the two classes are in different 53 components. (Obviously you can contrive 52 a scenario when they're in the same component, but 51 why would you ever do that? If you own both 50 pieces of code and release them in a single 49 component, it'd be mad ever to do this.) And 48 so BaseLogger should get its own LogName 47 property, which is exactly what happens. You 46 may have written:

SpecificLogger.Log("test");

but the C# compiler sees 45 that SpecificLogger doesn't provide a Log 44 method, so it turns this into:

BaseLogger.Log("test");

because that's 43 where the Log method is defined.

So whenever 42 you define a method in a derived class that 41 isn't attempting to override an existing 40 method, the C# compiler indicates this in 39 the metadata. (There's a "newslot" setting 38 in the method metadata that says, this method 37 is meant to be brand new, unrelated to anything 36 in the base class.)

But this gives you a 35 problem if you want to recompile CompD. Let's 34 say you've got a bug report due to some 33 entirely unrelated bit of code and you need 32 to release a new version of CompD. You compile 31 it against the new verison of CompB. If 30 the code you've written wasn't allowed, you 29 wouldn't actually be able to - old code 28 that's already compiled would work, but 27 you wouldn't be able to compile new versions 26 of that code, which would be a bit mad.

And 25 so, to support this (frankly somewhat obscure) scenario, they 24 allow you to do this. They generate a warning 23 to let you know that you've got a naming 22 clash here. You need to supply the new keyword 21 to get rid of it.

This is an obscure scenario, but 20 if you want to support inheritance across 19 component boundaries, you need this, otherwise 18 the addition of new public or protected 17 members on a base class would invariably 16 be a breaking change. That's why this is 15 here. But it's bad practice ever to rely 14 on it, hence the fact that you get a compiler 13 warning. The use of the new keyword to get 12 rid of the warning should only ever be a 11 stopgap.

The bottom line is this: this feature 10 exists for one reason only, and that's to 9 get you out of a hole in situations where 8 a new version of some base class has added 7 a member that didn't previously exist, and 6 which clashes with a member that's already 5 on your derived class. If that's not the 4 situation you're in, don't use this feature.

(I 3 think they should actually issue an error 2 rather than a warning when you leave out 1 new, to make this more clear.)

Score: 2

Static methods and fields do not belong 9 to class instances but to class definitions. Static 8 methods do not play part in the virtual 7 dispatching mechanism and are not part of 6 the virtual method table.

They are just methods 5 and fields on that specific class.

It may 4 look like the methods and fields are "inherited" because 3 you can do SpecificLogger.Log(), but that is just something 2 to keep you from having to refer to the 1 base class all the time.

Static methods and fields really are just global methods and fields, just the OO kind.

Score: 1

for my surprise following code is allowed 2 and compiles without any error on .net Framework 1 4.5.1, VS 2013.

class A
{
    public static void Foo()
    {
    }
}

class B : A
{

}

class Program
{
    static void main(string[] args)
    {
        B.Foo();
    }
}
Score: 0

You aren't overriding the property in the 11 base class, but instead hiding it. The actual 10 property used at runtime depends on what 9 interface you're working against. The following 8 example illustrates:

SpecificLogger a = new SpecificLogger();
BaseLogger b = new SpecificLogger();

Console.Write(a.Log); // Specific
Console.Write(b.Log); // null

In your code the Log 7 method is actually working against the BaseLogger 6 interface - because the Log method is part 5 of the BaseLogger class.

Static methods and 4 properties can not be overridden, and when 3 you want to hide a property you should use 2 the new keyword to denote that you're hiding 1 something.

More Related questions