[API Proposal]: TypeDescriptor: Add generic overloads to supply Type argument
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
### Background and motivation
All of System.ComponentModel.TypeDescriptor's entry points are currently static and currently lean on either Type or object parameters (e.g., GetConverter(Type), GetEditor(Type, Type), GetAttributes(Type)), which callers often use by passing typeof(<>) and casting return types. But design precedent in .NET has consistently guided development towards generic overloads to improve ergonomics, safety, and analyzability when the type argument is known:
- IServiceProvider usage is universally guided toward GetService() / GetRequiredService() extension methods rather than the non-generic GetService(Type).
- ActivatorUtilities.CreateInstance(…) complements the non-generic factory methods for DI-activated construction.
- Roslyn rule CA2263 – Prefer generic overload when type is known encodes this guidance to reduce boxing/casting and improve clarity. Adding TypeDescriptor generics would align with this rule.
### API Proposal
```csharp
namespace System.ComponentModel
{
public sealed class TypeDescriptor
{
public static TypeDescriptionProvider AddAttributes(params Attribute[] attributes);
public static TypeDescriptionProvider AddAttributes(T instance, params Attribute[] attributes);
public static void AddEditorTable(Hashtable table);
public static void AddProvider(TypeDescriptionProvider provider, T instance);
public static void AddProvider(TypeDescriptionProvider provider);
public static void AddProviderTransparent(TypeDescriptionProvider provider, T instance);
public static void AddProviderTransparent(TypeDescriptionProvider provider);
public static EventDescriptor CreateEvent<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] CT, T>(string name, params Attribute[] attributes);
public static EventDescriptor CreateEvent<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] CT>(EventDescriptor oldEventDescriptor, params Attribute[] attributes);
public static T? CreateInstance<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors)] T>(
IServiceProvider? provider,
Type[]? argTypes,
object?[]? args);
}
}
```
and so on...
### API Usage
Usages of some of the APIs such as:
```csharp
TypeDescriptor.AddProvider(myProvider, typeof(T));
T? instance = (T?)TypeDescriptor.CreateInstance(myProvider, typeof(T), [], []);
```
would become
```csharp
TypeDescriptor.AddProvider(myProvider);
T? instance = TypeDescriptor.CreateInstance(myProvider, [], []);
```
### Alternative Designs
_No response_
### Risks
Generic overload signatures might imply more trim compatibility than actually present.
Contributor guide
Assessment
This issue has not been assessed yet.