Replies: 17 comments 4 replies
-
I think
P.S. The curly braces should come after the where clause. Please fix the code. |
Beta Was this translation helpful? Give feedback.
-
Thanks, @Happypig375. Curly braces typos fixed. |
Beta Was this translation helpful? Give feedback.
-
Aside from being utterly confused as to how exclusive constraints are even useful, this is not even remotely the solution to the problem that you describe.
It's really not tricky, because your problem isn't about the constraints at all; it's all about overload resolution. // Intention: Resolves to AsSomething<T>(this IEnumerable<IEnumerable<T>> arg)
// Actuality: Resolves to AsSomething<T>(this IEnumerable<T> arg)
new[] { new[] { 1 } }.AsSomething(); What is actually happening is the compiler not inserting an implicit conversion from new[] { new[] { 1 }.AsEnumerable() }.AsSomething(); then it would pick your |
Beta Was this translation helpful? Give feedback.
-
Hi @Joe4evr! Thanks for your comments! Yes, the desired overload resolution can be achieved if explicit casting is done—but I'm trying to find a way to avoid requiring that casting. Real-Life ScenarioI authored a library that adapts an To me, the ideal interface would be a pair of extension methods named Of course, as we've been discussing, this doesn't work as C# stands today. Instead, either in some circumstances the library user is required to manually add a cast or separate method names must be used for the two variations of possible input. (My library went with the latter approach, using How Resolution Would WorkIf this proposal were implemented, I'd envision resolution behaving as follows: To resolve:
Against:
|
Beta Was this translation helpful? Give feedback.
-
I'm not sure how well this really works as a generic constraint. What you seem to want is explicitly a way to influence overload resolution, and (as you mention) the C# compiler doesn't consider generic constraints as a part of overload resolution. That has been suggested as a part of "bestest betterness". Otherwise constraints have a very different purpose, namely in limiting the behavior of the generic type argument so that the generic method may use it in a particular manner. The suggested While I understand the frustration in writing the generic methods for your library I think trying to manipulate the CLR (for the constraint) and the language specifically to support that constraint seems a little bit overkill. I don't know the implementation details of your library or what those two methods accomplish but what I might have done is have the one method interrogate the |
Beta Was this translation helpful? Give feedback.
-
Hello @HaloFour! I didn't realize that generic type arguments currently are not considered during the overload resolution process. Based on that, my Even if that proposal makes it into the language (which would open the door for my |
Beta Was this translation helpful? Give feedback.
-
I have an an additional use case for "not constraints". I'm developing an extension for For example I want this to cause a compilation error if
For motivations as to why I would want to create such an Api, there are numerous issues like this one dotnet/aspnetcore#5496 and it is basically because any instance of a transient service that the container creates automatically gets owned by the container and tracked for disposal.. but disposal doesn't happen until the container itself is disposed. Now consider you are resolving many transient instances from a root container or a scope that lives a long time - they accrue and you get memory leak. Much better imho to prevent transients that implement IDisposable from being registered at all but we need the compiler to enforce that with some kind of feature like this. |
Beta Was this translation helpful? Give feedback.
-
Another use case: #4038 |
Beta Was this translation helpful? Give feedback.
-
The simplest scenario that I have recently run into is 2 classes with same/similar generic constraint (often one inherits from another). Some Ts implement an interface and should be forced to utilize one of two possible objects, I have no way of enforcing the utilization f the correct class if T implements the interface. Assuming we have O1<T> and O2<T> and we want to constrain utilization of O2 when T : Interface. |
Beta Was this translation helpful? Give feedback.
-
I've also run into wanting this - I'm trying to write an extension for
intending the call at the end to call the version of the method that can only take |
Beta Was this translation helpful? Give feedback.
-
I have also a use case for the not/! operator in generic constraints: I'm using MediatR in my Web Api and wrote a Pipeline Behavior which should be executed for ALL request types but one. Without the not/! operator I have to add a marker interface to all request classes except one. |
Beta Was this translation helpful? Give feedback.
-
I would really like a |
Beta Was this translation helpful? Give feedback.
-
Actually, a feature like this is already in use in a standard installation. E. g.
raises a CS0453 |
Beta Was this translation helpful? Give feedback.
-
I support advancing the type system |
Beta Was this translation helpful? Give feedback.
-
Yes, please, the type system really needs more flexibility as other languages move past the feature-set & ergonomics of C# (The lang, not necessarily .Net). The language design was amazing 10 years ago, but it's becoming more and more constraining as time goes on. We keep getting new sugar & features, but the type system seems stuck in time. We shouldn't have to rely on runtime type checking when that could be done at compile time, which is a not-insignificant portion of the C# that ends up being written around a business domain. As for the folks that run on "I don't see how this is useful" look no further than TypeScript. |
Beta Was this translation helpful? Give feedback.
-
This needs to be implemented, and should be usable in conjunction with the normal type constraint where each addition increases the specificity e.g In my experience people rarely use the type constraints because it lacks more flexible specificity. Right now it's pretty much all or nothing - you either pick class/struct or the end of a branch e.g int |
Beta Was this translation helpful? Give feedback.
-
I have another use case. I was making an IVector<TSelf, TInternal> interface and wanted to do this: public interface IVector<TSelf, TInternal> :
// Add 2 vectors together
IAdditionOperators<TSelf, TSelf, TSelf>,
// Add a number to every component, ex. new Vector2(1, 2) + 3
IAdditionOperators<TSelf, TInternal, TSelf> This leaves us with: I would like to do: public interface IVector<TSelf, TInternal> :
// Add 2 vectors together
IAdditionOperators<TSelf, TSelf, TSelf>,
// Add a number to every component, ex. new Vector2(1, 2) + 3
IAdditionOperators<TSelf, TInternal, TSelf>
where TInternal : !TSelf Which results in no error. |
Beta Was this translation helpful? Give feedback.
-
Looking at this repository's list of issues, there are a lot of ideas relating to generics. Here’s another one to add to the mix.
Motivation
If a developer wants to provide method overloads handling specific type parameter cases along with a more general ‘catch all’ overload, it can be tricky to get the complier to resolve to the intended specific type case overload.
For example, the intention below is that the
AsSomething()
call on the nested array be resolved to the first extension method. However, the C# complier resolves it to the second method.(Based off a real-world situation adapting
IEnumerable<T>
s toIDataReader
. Each item in the enumerable became a data reader record. IfT
was itself anIEnumerable<>
, the items in the inner enumerable become the values of the data reader’s fields. Otherwise,T
's publicly readable instance properties become the data reader’s field values. Unfortunately, using a pair of overloads similar to the above didn’t work due to the way the complier handled resolution.)Idea
Allow more influence over the overload resolution process by indicating that a certain type parameter must not match a given constraint. This could be achieved by allowing the type constraint list to contain
not
constraints.If this were implemented:
not
constraints should allow open (e.g.IEnumerable<>
) and partially open (e.g.Dictionary<int,>
) types.not
constraints should be allowed in a type constraint list (e.g.where T : not IComparable, T : not IConverable
).Beta Was this translation helpful? Give feedback.
All reactions