Type of issue
Outdated article
Description
CS0465 documentation says:
This warning occurs when you create a class with a method whose signature is public virtual void Finalize.
If such a class is used as a base class and if the deriving class defines a finalizer, the finalizer will override the base class Finalize method, not Finalize.
However, currently (used from VS 18.9.1 on Windows 11 x64, targeting .NET 10 AnyCPU), the actual behavior is different.
- The warning is (IMO correctly) emitted for all accessibility modifiers (except
private, which C# anyway doesn't allow for virtual methods).
- Suppose
B introduces protected virtual void Finalize() { } (new slot).
- Suppose
D : B defines a finalizer ~D() { }.
The effect is as follows:
D's finalizer overrides both B.Finalize and object.Finalize. The C# compiler emits explicit .override object::Finalize() in D's synthesized Finalize, so it does override object.Finalize. The method is also non-newslot and virtual, so it overrides B.Finalize due to matching name and signature.
D's finalizer will call instance B.Finalize, which is, of course, not the finalizer (I take "finalizer" to mean the override of object.Finalize).
More interestingly, if B.Finalize is...
public or internal or protected internal, then type D fails to load (override cannot reduce access);
private protected, then D.Finalize overrides B.Finalize and object.Finalize, and in D.Finalize, it calls object.Finalize not B.Finalize (this happens even if B.Finalize is accessible to D);
- non-
virtual but protected or protected internal, then D.Finalize will call B.Finalize (and not object.Finalize), but of course only overrides object.Finalize.
Maybe the documentation was accurate for some versions of C# compiler. I suspect the situation is simply unsupported as defining a method called Finalize (except via the finalizer syntax) is anyway a very bad idea. If both are true, I suggest avoiding describing what happens when one defines such a method, and simply say "doing so interferes with finalization logic".
Page URL
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs0465?f1url=%3FappId%3Droslyn%26k%3Dk(CS0465)
Content source URL
https://github.com/dotnet/docs/blob/main/docs/csharp/language-reference/compiler-messages/cs0465.md
Document Version Independent Id
53f17a1d-75c8-7fe6-1b0c-7893ae6fc0c4
Platform Id
ac53118f-3da2-cf27-577d-9745af24231b
Article author
@BillWagner
Metadata
- ID: 93138196-598c-7726-1b74-4cb6e4b302a3
- PlatformId: ac53118f-3da2-cf27-577d-9745af24231b
- Service: dotnet-csharp
- Sub-service: errors-warnings
Related Issues
Associated WorkItem - 627639
Type of issue
Outdated article
Description
CS0465 documentation says:
However, currently (used from VS 18.9.1 on Windows 11 x64, targeting .NET 10 AnyCPU), the actual behavior is different.
private, which C# anyway doesn't allow forvirtualmethods).Bintroducesprotected virtual void Finalize() { }(new slot).D : Bdefines a finalizer~D() { }.The effect is as follows:
D's finalizer overrides bothB.Finalizeandobject.Finalize. The C# compiler emits explicit.override object::Finalize()inD's synthesizedFinalize, so it does overrideobject.Finalize. The method is also non-newslotandvirtual, so it overridesB.Finalizedue to matching name and signature.D's finalizer willcall instance B.Finalize, which is, of course, not the finalizer (I take "finalizer" to mean the override ofobject.Finalize).More interestingly, if
B.Finalizeis...publicorinternalorprotected internal, then typeDfails to load (override cannot reduce access);private protected, thenD.FinalizeoverridesB.Finalizeandobject.Finalize, and inD.Finalize, it callsobject.FinalizenotB.Finalize(this happens even ifB.Finalizeis accessible toD);virtualbutprotectedorprotected internal, thenD.Finalizewill callB.Finalize(and notobject.Finalize), but of course only overridesobject.Finalize.Maybe the documentation was accurate for some versions of C# compiler. I suspect the situation is simply unsupported as defining a method called
Finalize(except via the finalizer syntax) is anyway a very bad idea. If both are true, I suggest avoiding describing what happens when one defines such a method, and simply say "doing so interferes with finalization logic".Page URL
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/cs0465?f1url=%3FappId%3Droslyn%26k%3Dk(CS0465)
Content source URL
https://github.com/dotnet/docs/blob/main/docs/csharp/language-reference/compiler-messages/cs0465.md
Document Version Independent Id
53f17a1d-75c8-7fe6-1b0c-7893ae6fc0c4
Platform Id
ac53118f-3da2-cf27-577d-9745af24231b
Article author
@BillWagner
Metadata
Related Issues
Associated WorkItem - 627639