Proposal: define signatures for generic type parameters #1387
Replies: 17 comments
-
How is this different/better than 'Shapes/Extensions': #164 Thanks! |
Beta Was this translation helpful? Give feedback.
-
@CyrusNajmabadi |
Beta Was this translation helpful? Give feedback.
-
Can you explain what this means: // so compiler must allow codes like this:
var n = Num.Parse("10") ;
var n += n * n + 2; how would that work? + on two ints is very different from + on two longs. |
Beta Was this translation helpful? Give feedback.
-
I already did:
in design time, the compiler just lit is pass. In runtime,if Num is int it will be:
So, no more action is needed. |
Beta Was this translation helpful? Give feedback.
-
Sorry, i don't get how this would actually work. What code would actually get generated here. How would it make sure that the right operators were actually called at runtime? |
Beta Was this translation helpful? Give feedback.
-
If you are confused because I used + 2 in the example, maybe you are right. If I did this and the compiler complains about the conversion from 2 to Num, I would modify the Num signature to add a conversion operator from int To Num, or a + operator that accepts Num and int. |
Beta Was this translation helpful? Give feedback.
-
Could you explain then how this is different from you just creating a Num struct and adding those operators to it yourself? In other words, it sounds like you can already do this today. So why would we need to change the language here? |
Beta Was this translation helpful? Give feedback.
-
Or use double for all numeric operations! |
Beta Was this translation helpful? Give feedback.
-
I don't understand your proposal. You say you just want to have implicit conversions to Num so you can have these operators defined in one place. But you can already have that today. You then say:
But haven't explained how your proposal makes the cost low. How does your proposal actually work. For example, can you explain the IL that hte compiler would generate when it encounters these constructs? I'm trying to figure out what it would actually get compiled down to and how it would ensure that "But the cost is high" would not be true. Thanks! |
Beta Was this translation helpful? Give feedback.
-
Is it regualar to ask a C# programmer about IL code? This is not my area. I only make a suggestion from a programmer's point of view, and you tell me if it is doable or not. This is why we discuss. |
Beta Was this translation helpful? Give feedback.
-
It's your proposal, it's important to at least be able to explain certain parts of it. Right now i'm not seeing how you would do this. As such, i need more information from you here. |
Beta Was this translation helpful? Give feedback.
-
True. But it is also a teamwork in an open source community, so, I welcome any addition or correction. |
Beta Was this translation helpful? Give feedback.
-
Given how you've described things so far (especially your bit about: "I would modify the Num signature to add a conversion operator from int To Num, or a + operator that accepts Num and int.") then i would just do this today in C# using a "struct Num" with implicit conversions in it. It doesn't seem like you need a new language feature. |
Beta Was this translation helpful? Give feedback.
-
Please read the links I mentioned before. This issue is marked as a future work in CoreFx, because this is a problem in other areas like tensor |
Beta Was this translation helpful? Give feedback.
-
I read the links. You still haven't addressed how this would work. Also, my comment about having a "struct Num" said nothing about using an 'object' as the internal representation. One of the linked post also said this:
I agree with this advice. Shapes/Extensions has a rich proposal behind it, handles a superset of the use cases that you seem to care about, and actually provides a way that explains how this would generate code. |
Beta Was this translation helpful? Give feedback.
-
The idea is just to guarantee that T supports a certain set of operations, right? Perhaps the intent is more obvious this way? (and more inline with existing syntax)
class NumList<T>
where T : Num // <- here is where we declare what T must be capable of
{
public void AddFromText(string text) => _inner.Add(T.Parse(text));
public T Sum() => _inner.Aggregate((acc, v) => acc + v);
} Elsewhere: var list = new NumList<int>();
list.AddFromText("15");
list.AddFromText("17");
var sum = list.Sum(); @MohammadHamdyGhanem. I think what Cyrus is saying is that we must generate one shared piece of IL for class NumList (or foo in your example), and that's not trivial (or even possible, perhaps) because the function calls would be different depending on what actual T you used (byte, int etc.). @CyrusNajmabadi. To answer the question of "what code would actually get generated?". I think the constraint Num could potentially generate a generic interface with the various required methods, and then generate an implementation of that interface for each of the supported base types (basically thunks to the real methods). NumList would generate code bound against the interface (presumably instanced in the constructor according to T, and stored in a hidden field). I'm sure this would be a lot more useful if the constraint was open though, i.e. you don't say what the valid types are, rather it just uses "duck typing" to match the various methods. In that case it's not as clear who would generate the thunks. And reflection based construction through MakeGenericType() is even more of a mystery. |
Beta Was this translation helpful? Give feedback.
-
I faced a situation where I need to define a method accepts a char or Escapes as a parameter, where Escapes is defined as this:
I solved this by defining this class:
Now, it is possible to use CharOrEscape as a parameter, and treat it in code as string:
So, I can use this method like this:
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Regarding these two issues:
https://github.com/dotnet/corefx/issues/27167
#1233
I had a new suggestion to make more control of the generic type parameters:
In addition to constraints for generics, I suggest to allow us to define signatures for generic type parameters, such as:
The above code tells the compiler that:
1- Num can only be one of the members mentioned in the type list: {byte, short, int, long}. Compiler must raise error for any other types.
2- Num has the Parse method, and can be used with the + and * operators, so compiler must allow codes like this:
This will be helpful when there is no suitable interface or base class to use as a constraint, which is the case of numeric types.
When Num is used as a type parameter, the compiler can use our provided signature to grantee that the code that seems late-pound is trusted in design time, and will work at run time. So, it is an early bound a like code, thanks to our generic signature.
So, the compiler can accept this:
Benefits:
1- Not breaking any existing code.
2- No need for any change in CoreFX, but it requires additions to Roslyn and IL. There is no way to convert the generic signature to an interface, because interfaces doesn't accept static members, and also primitive numeric types doesn't overload arithmetic operators although they arte applied to them!
3- Has no impact on the runtime performance.
4- Generic signatures are reusable. so we can define as many signatures as we want for different cases, and put them in reusable modules.
Note:
Signature inheritance may be useful.. something like:
Num2 combines its members list with that of Nums, and has all its members.
Beta Was this translation helpful? Give feedback.
All reactions