Runtime: Extend usage of DisplayNameAttribute

Created on 13 Jun 2019  路  11Comments  路  Source: dotnet/runtime

DisplayNameAttribute currently only has the UsageAttribute targets shown below. This limits how the DisplayNameAttribute can be used. The targets should be extended to allow specifying display names for enums and structs.

[AttributeUsage(AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Class | AttributeTargets.Method)]

Rationale and usage

It can be useful to define DisplayNames for enum elements, like this:

public enum FriendlyColorsEnum
{
    [DisplayName("Blanched Almond Color")]
    BlanchedAlmond = 1,
    [DisplayName("Dark Sea Green Color")]
    DarkSeaGreen = 2,
    [DisplayName("Deep Sky Blue Color")]
    DeepSkyBlue = 3,
    [DisplayName("Rosy Brown Color")]
    RosyBrown = 4
}

The example was taken from someone else who used the DescriptionAttribute instead.

While it is possible to use the DescriptionAttribute it has a different meaning, and it could make sense to use both the DisplayNameAttribute and the DescriptionAttribute on the same elements.

The benefit of using an attribute is that the display name is not limited by the naming rules of the programming language. For instance it can include spaces, special characters, start with a number. It is possible to implement a custom attribute, but that makes the code more complex.

In addition to enabling the use of DisplayNameAttribute on enums it seems sensible to also enable it for structs.

Proposed change

My proposal is to change the targets to All, since that is what is used for DescriptionAttribute. It might not make sense to apply the DisplayName on every target, but I am also not aware of drawbacks to allowing it for all targets.

[AttributeUsage(AttributeTargets.All)]

A more limited target could suffice but that would need a more detailed look at the trade-offs for each target.

area-System.ComponentModel bug

Most helpful comment

It looks like this might have been broken in .net core 3.0. I'm trying to upgrade a project from .net core 2.2 to 3.0 and I'm getting the following error Attribute 'DisplayName' is not valid on this declaration type. It is only valid on 'class, method, property, indexer, event' declarations. Here is my enum declaration for reference.

public enum ComparisonType
{
Undefined = 0,
National = 1,
[DisplayName("Peer Group")]
PeerGroup = 2,
}

All 11 comments

It looks like this might have been broken in .net core 3.0. I'm trying to upgrade a project from .net core 2.2 to 3.0 and I'm getting the following error Attribute 'DisplayName' is not valid on this declaration type. It is only valid on 'class, method, property, indexer, event' declarations. Here is my enum declaration for reference.

public enum ComparisonType
{
Undefined = 0,
National = 1,
[DisplayName("Peer Group")]
PeerGroup = 2,
}

We've got that issue as well.

Seeing the same on a migration from 2.2 to 3.1.1

Also encountering this issue when migrating from 2.1 to 3.1.1.

For those interested, a possible workaround might be using the DisplayAttribute instead of DisplayNameAttribute.

Looks like DisplayNameAttribute inadvertently omitted its AttributeUsageAttribute in the reference assembly prior to 3.x.
https://github.com/dotnet/corefx/blob/4681a68852b4e790c1d743ec7d1825bcd5ff9260/src/System.ComponentModel.Primitives/ref/System.ComponentModel.Primitives.cs#L139

The attribute was missing in .NETCoreApp, but present in .NETStandard, https://github.com/dotnet/standard/blob/52777e1506d39f64d12550e0703c4bd5e7e9f218/netstandard/ref/System.cs#L1638

I brought this back with https://github.com/dotnet/runtime/commit/a58e4fb6481228b02e2c44f3acd54efa578a81de#diff-66eed886fd01ffb17d8e43424a30a0d3R145 which made 3.x consistent with .NETFramework, .NETStandard, and the .NETCore implementation.

It seems reasonable for us to bring this back.

What's the consuming scenario that will read the attribute from enum values? TypeDescriptor? I want to make sure the end-to-end is considered and tested (to avoid future regressions and ensure a complete solution).

Tagging subscribers to this area: @safern
See info in area-owners.md if you want to be subscribed.

What's the consuming scenario that will read the attribute from enum values? TypeDescriptor? I want to make sure the end-to-end is considered and tested (to avoid future regressions and ensure a complete solution).

For me the most common use case would be scenarios where an enum makes the most sense for code flow, but then also needing "user friendly" text. Granted this could be handled in a mapping object, but the syntax sugar here allows for cleaner field management (IMO).

@ericstj

What's the consuming scenario that will read the attribute from enum values?

My use case is that I have a custom generic type converter to convert enums that I use in data binding. My code uses reflection (GetCustomAttributes<>) to look for the attribute and convert to/from other data types (in this case strings).

Using the existing DisplayName attribute makes it easier to work with compared to implementing a third party attribute, mostly because the programmer only has to learn a single attribute and it can be shared between different projects/libraries instead of each rolling their own.

To be clear, no-one here is expecting the runtime (EG: TypeDescriptor) to read this attribute in the new scenarios?

It's not a regression from "last" release anymore

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Timovzl picture Timovzl  路  3Comments

omajid picture omajid  路  3Comments

yahorsi picture yahorsi  路  3Comments

chunseoklee picture chunseoklee  路  3Comments

aggieben picture aggieben  路  3Comments