Enum Deletion Enterprise
The C# compiler inlines enum backing values at all call sites — the literal fields on an enum type exist only for reflection (Enum.ToString(), Enum.Parse(), Enum.IsDefined()). Demeanor deletes these fields, leaving decompilers with empty enums that have no symbolic names or values.
Usage
| CLI | MSBuild | Default |
|---|---|---|
| (enabled by default at Enterprise) | (enabled by default at Enterprise) | On |
--no-enum-deletion | <ObfuscateNoEnumDeletion>true</ObfuscateNoEnumDeletion> | Disable |
Before & After
public enum DiscountType
{
None = 0,
Percentage = 1,
FixedAmount = 2,
BuyOneGetOne = 3,
Seasonal = 4,
Employee = 5,
}
public enum TaxRegion
{
None = 0,
US = 1,
EU = 2,
UK = 3,
Japan = 4,
}public enum g
{
}
public enum h
{
}Real ILSpy output. Both enums are empty — all 11 literal fields deleted. Code that used DiscountType.Percentage still works because the compiler inlined the value 1 at every call site. Enum.ToString() now returns "1" instead of "Percentage".
How It Works
After renaming, Demeanor iterates all enum types and removes every static literal field. The special value__ instance field (which holds the underlying integer at runtime) and the TypeDef itself are preserved — method signatures, local variables, and fields still reference the enum type.
The Constant metadata rows, CustomAttribute rows, and any other dependent metadata for each deleted field are automatically cleaned up.
Effect on Decompiled Code
Before deletion, a decompiler shows DiscountType.BuyOneGetOne. After deletion, it shows (g)3 — a cast of the raw integer to the unnamed enum type. Switch statements that used symbolic names become numeric:
// Before: meaningful switch
case DiscountType.BuyOneGetOne:
num = _basePrice / 2m;
// After: raw integers
case (g)3:
num = this.m_a / 2m; When to Disable
Enum.ToString()— if your application displays enum member names to users (e.g., in logs or UI), those will show raw integers after deletion. Exclude specific enums with[Obfuscation(Exclude = true)].Enum.Parse()/Enum.IsDefined()— parsing enum values from configuration files or user input by name will fail.- Serialization — JSON serializers that write enum names (not values) will produce integers. Most serializers default to numeric values, which still work.
Ready to protect your .NET code?