There are numerous performance benefits to sealing types:
public class C { internal void Call(SealedType o) => o.M(); internal void Call(NonSealedType o) => o.M(); } internal class BaseType { public virtual void M() {} } internal class NonSealedType : BaseType { public override void M() {} } internal sealed class SealedType : BaseType { public override void M() {} }
results in:
C.Call(SealedType)
L0000: cmp [rdx], edx
L0002: ret
C.Call(NonSealedType)
L0000: mov rcx, rdx
L0003: mov rax, [rdx]
L0006: mov rax, [rax+0x40]
L000a: mov rax, [rax+0x20]
L000e: jmp rax
is
/as
type checks for the type can be done more efficiently, as it only needs to compare the type itself rather than account for a potential hierarchy.public class C { public bool IsSealed(Object o) => o is SealedType; public bool IsNotSealed(Object o) => o is NonSealedType; } internal class NonSealedType { } internal sealed class SealedType { }
results in:
C.IsSealed(System.Object)
L0000: test rdx, rdx
L0003: je short L0016
L0005: mov rax, 0x7ff7ab9ad180
L000f: cmp [rdx], rax
L0012: je short L0016
L0014: xor edx, edx
L0016: test rdx, rdx
L0019: setne al
L001c: movzx eax, al
L001f: ret
C.IsNotSealed(System.Object)
L0000: sub rsp, 0x28
L0004: mov rcx, 0x7ff7ab9ad048
L000e: call System.Runtime.CompilerServices.CastHelpers.IsInstanceOfClass(Void*, System.Object)
L0013: test rax, rax
L0016: setne al
L0019: movzx eax, al
L001c: add rsp, 0x28
L0020: ret
public class C { internal void StoreSealed(SealedType[] arr, SealedType item) => arr[0] = item; internal void StoreNonSealed(NonSealedType[] arr, NonSealedType item) => arr[0] = item; } internal class NonSealedType { } internal sealed class SealedType { }
results in:
C.StoreSealed(SealedType[], SealedType)
L0000: sub rsp, 0x28
L0004: cmp dword ptr [rdx+8], 0
L0008: jbe short L001c
L000a: lea rcx, [rdx+0x10]
L000e: mov rdx, r8
L0011: call 0x00007ff801db9f80
L0016: nop
L0017: add rsp, 0x28
L001b: ret
L001c: call 0x00007ff801f0bc70
L0021: int3
C.StoreNonSealed(NonSealedType[], NonSealedType)
L0000: sub rsp, 0x28
L0004: mov rcx, rdx
L0007: xor edx, edx
L0009: call System.Runtime.CompilerServices.CastHelpers.StelemRef(System.Array, Int32, System.Object)
L000e: nop
L000f: add rsp, 0x28
L0013: ret
using System; public class C { internal Span<SealedType> CreateSealed(SealedType[] arr) => arr; internal Span<NonSealedType> CreateNonSealedType(NonSealedType[] arr) => arr; } internal class NonSealedType { } internal sealed class SealedType { }
results in:
C.CreateSealed(SealedType[])
L0000: test r8, r8
L0003: jne short L000b
L0005: xor eax, eax
L0007: xor ecx, ecx
L0009: jmp short L0013
L000b: lea rax, [r8+0x10]
L000f: mov ecx, [r8+8]
L0013: mov [rdx], rax
L0016: mov [rdx+8], ecx
L0019: mov rax, rdx
L001c: ret
C.CreateNonSealedType(NonSealedType[])
L0000: sub rsp, 0x28
L0004: test r8, r8
L0007: jne short L000f
L0009: xor eax, eax
L000b: xor ecx, ecx
L000d: jmp short L0026
L000f: mov rax, 0x7ff7aba4d870
L0019: cmp [r8], rax
L001c: jne short L0034
L001e: lea rax, [r8+0x10]
L0022: mov ecx, [r8+8]
L0026: mov [rdx], rax
L0029: mov [rdx+8], ecx
L002c: mov rax, rdx
L002f: add rsp, 0x28
L0033: ret
L0034: call System.ThrowHelper.ThrowArrayTypeMismatchException()
L0039: int3
We should add an analyzer, at either hidden or info level but that we’d look to turn on as a warning in dotnet/runtime, that flags:
and flag that they should be sealed. A fixer would seal the type. We could also make it configurable on the visibility, in case someone wanted to e.g. also opt-in public types (we wouldn't/couldn't in dotnet/runtime). We could also optionally factor in whether the type declares any new virtual methods, a protected ctor, or anything else that suggests the type is intended for derivation... upon detecting such things, we could either choose not to warn, or we could warn with a different diagnostic id.
If a developer working in the library ever wants to derive from such a type, they can remove the sealed when they add the derivation.
SingleAccretion, omariom, antoniofreire, Wraith2, gfoidl and 30 moreairbreather, DavidArno, mic-max, Emik03, DoCode and 1 more
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4