Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Add a new constraint: accepts a generic type. #1471

Closed
Lattyware opened this issue Apr 22, 2018 · 2 comments
Closed

Proposal: Add a new constraint: accepts a generic type. #1471

Lattyware opened this issue Apr 22, 2018 · 2 comments

Comments

@Lattyware
Copy link

Lattyware commented Apr 22, 2018

A new constraint that can be applied to a type parameter: where T : <>

This would mean that T is a generic type that takes a single type parameter itself. (presumably T<,> for two parameters, etc...).

A use case:

public class TypeLinkedDictionary {
    private readonly Dictionary<object, object> dictionary;

    public TypeLinkedDictionary() {
        dictionary = new Dictionary<object, object>();
    }

    public void Add<TShared>(Key<TShared> key, Value<TShared> value) => dictionary.Add(key, value);

    public Value<TShared> Get<TShared>(Key<TShared> key) => (Value<TShared>) dictionary[key];
}

public class Key<T> {
}

public class Value<T> {
}

Here we have a dictionary that has a link between the key and value types. This type can be different for each pair, but has to be the same for the key and the value.

If we want to make a generic version of this for an arbitrary Key and Value, it's impossible to keep this link between them.

With this proposal, the solution looks like this:

public class TypeLinkedDictionary<TKey, TValue> where TKey : <> where TValue : <> {
    private readonly Dictionary<object, object> dictionary;

    public TypeLinkedDictionary() {
        dictionary = new Dictionary<object, object>();
    }

    public void Add<TShared>(TKey<TShared> key, TValue<TShared> value) => dictionary.Add(key, value);

    public TValue<TShared> Get<TShared>(TKey<TShared> key) => (TValue<TShared>) dictionary[key];
}

Note that I am specifically not suggesting the ability to use T as some kind of base type parent to any T<> or T<?> type - rather, it can only be used by filling the parameter. As I understand it this should be plausible to implement.

Where the type argument given has generic constraints, this adds complexity. These constraints would need to be added to any generic types that are used as arguments for the parameter under this constraint. E.g:

public class Key<T> where T : struct {
}

Would result in the methods having the where TShared : struct constraint added, for example, where Key was used as TKey.

This would also need to work in reverse, where any type used as a parameter to the type given in this new constraint would also need to be non-contradictory with the constraints as it is being used. E.g:

public void Add<TShared>(TKey<TShared> key, TValue<TShared> value) where TShared : class => dictionary.Add(key, value);

Would result in the above Key<T> with a struct constraint not being a valid choice as a type parameter for TKey. This is heavily linked to the potential to do, for example, Key<int> and give a specific type.

This adds complexity - both in implementation and the reading of the resulting code, so another option would be to disallow constraints over types used as type arguments, or even over types used as arguments to this.

@svick
Copy link
Contributor

svick commented Apr 22, 2018

I think this sounds like a duplicate of #339.

@Lattyware
Copy link
Author

You are entirely right - I searched to try and find an issue talking about this idea, but didn't find that one. I'll close this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants