-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Tuple types in using directives #423
Comments
I'd like to see |
Global usings sounds like something I would use. I like the generic declaration too.. Let's turn usings into full on type aliases! |
I want two things for two different reasons:
|
Regarding this: Can this be added in something like C# 7.1? I mean it is necessary ASAP. We can declare tuple like this: And work with (bool Gender, double Age) as Subject Otherwise we will have to use structs as usual... no benefits from new tuples... |
I disagree. I'm using tuples over structs to great effect already. Though I am looking forward to using aliases in general, including this. |
If you want to abandon your code clarity it is your choice! But stop propagation of that! This code de-facto is much less readable without tuples aliases:
So I will repeat my question.. Why can we do this?
But not this?
Or at least this?
@DavidArno It should NOT be global! It is local alias of type and should be local! |
It's clear you want these local aliases. What's way less clear to me, is what use they'd be. I've never used a type alias and really cannot see how your dictionary example would improve my code. Tuples though have obvious use cases in my view and are the single best feature of C#7. I'm looking forward to records, but not this alias suggestion. |
As I directly specified above: for code clarity...
It is not about your code it is about my code.. which can look like example provided above... |
If you have 10 parameters, creating an alias would be sticking a plaster over the infected cut. That's not clarity; that's denial. If you have a 10 parameter tuple then it's time to pull up those refactoring tools and get addressing that. And for your example, I'm not sure you have understood how to use tuples as you appear to be fighting them, rather than working with them. A simple way to do what you are trying to do, is: class C
{
private Dictionary<string, (string Name, string Surname, bool Active)> _dictionary = ...
void M()
{
if (_dictionary.TryGetValue("a", out var value))
{
// value.Name, value.Surname and value.Active are all in scope here
}
...
} |
I do not agree. if we need 10 parameters we still need 10 parameters.. And it should be represented in most clear way available in language for the moment. And tuples without aliases are not the ones. For now it is solved with structs, but it is additional definition which I want to avoid with aliases and new tuples.
You will have to specify this tuple everywhere... in each method accepting this value.. or returning this value... in other words in all code related to this tuple or this dictionary. Once again it is question of clarity... Anything complex (massive) is not clear by its definition.
Nice trick... But...
|
Ah, I see the problem. What I see as the correct way to use tuples, you see as "tricks". What I see as the best way to write code, you see as "evil". What you see as "clarity", I see as badly written code. Clearly our views are too divergent at a fundamental level for any further meaningful discussion. |
Reading back through this thread is an interesting view on how my take on some ideas changes over time. I started out liking the idea of being able to express something like: // Subject.cs
global using Subject<T> = (T Gender, double Age); Then I decided that there was little point to this if we had records. I now find this view reversed: there actually seems little point to records if we can have global aliases like the above. |
Metadata. Conversion operators. Interface implementations. |
I do not see any point to treat your opinion as correct. Just one very simple thing to show your manner of discussion: P.S. |
In my experience, conversion operators are more trouble than they are worth. Why would you want a pure data type to implement an interface? Metadata? Maybe... |
You may find it useful to read up on consensus fallacies. Whilst you are at it, it might help to read about false dichotomies too. |
Conversion operators can be useful for value types. For example For the interface I guess you could provide an Metadata I think is obvious since ORM objects is an obvious use-case for records. |
Damn, I might have to flip-flop again! 😀 |
Speaking of public struct Id<TEntity, TId>(TId Value);
using Gid<TEntity> = Id<TEntity, Guid>;
using CustomerId = Id<Customer, long>;
public class Api
{
public SynergizeCustomerRelation(CustomerId id);
public CorrelateProfitAgility(Gid<Quarter> quarter);
} It could be useful to have those type aliases available to API consumers as well. |
Exactly what I want to say.. You do not have any arguments even in very simple technical questions. And you try to guard yourself with high-flown words! Non limitus hominus dolboebus! |
Nice example that actually shows the benefit of having both records and global type aliases. This could be achieved using public struct Id<TEntity, TId>(TId Value);
public using Gid<TEntity> = Id<TEntity, Guid>;
public using CustomerId = Id<Customer, long>;
public class Api
{
public SynergizeCustomerRelation(CustomerId id);
public CorrelateProfitAgility(Gid<Quarter> quarter);
} Could use fairly standard scoping rules: using Alias = Type; // local to file
private using Alias = Type; // same as above; "private" thus optional as it's the default
internal using Alias = Type; // alias exposed to this project/assembly
public using Alias = Type; // alias exposed to all consumers of this assembly |
Also remember that aliases can't reference other aliases, only fully qualified types. So you wouldn't be able to alias a named tuple and then use that alias as generic type arguments in other aliases. You'd need to submit another proposal to expand those rules, which will likely have to include ways that the compiler can avoid circular references. |
@HardHub Using |
@jnm2, anonymous types is single valid usage for var.. for all other cases it is bad practice... I am just voting to add aliases for tuples as it is now for all other types... You can do this: but not this: I think it is ridiculous... |
@HardHub I agree that aliases would be useful. There is plenty of developer consensus on both sides of the |
I can't remember which of the language team recently said it, but a good rule of thumb here is:
|
See, as to #2, I'd say that to properly understand the returned value's type in context, you'd want to start by look at the method returning it anyway. Once you do that, the type name is right in front of you. 😈 (In my experience there are very few times outside the IDE where if the type isn't obvious I don't end up having to look at the method for other reasons too.) |
Would be great to have this in v 7.x .. as it now seems v8 is late and may not include records .. |
A C# release is never late, nor is it early, it arrives precisely when it means to. |
(like Chuck Norris ...) |
I am very much looking forward to it. Clarity. Repeated type (tuple) declarations require readers to carefully inspect each to ensure they are identical. Efficiency. Edit once, change everywhere. Consistency. The current limitation on aliasing tuples (but not generic that use tuples?!) is just one more inconsistency that folks encounter in learning C# today. |
Why is not this proposal a champion? |
No LDM member has felt passionate enough about this proposal yet to take ownership and drive it. Most likely there are other proposal that they feel are more worthwhile at this point. |
@jcouv protected List<(Char from, Char to)> Ranges = new List<(Char from, Char to)>();
public CharClass(params (Char from, Char to)[] ranges){
} it can be: protected List<Range> Ranges = new List<Range>();
public CharClass(params Range[] ranges){
} |
@MohammadHamdyGhanem I would recommend participating in these discussions over at gitter.im/dotnet/roslyn or gitterim/dotnet/csharplang. People will be able to answer your questions quickly and you can hvae the sort of discussions you seem to want to participate in. Cheers! |
Still no LDM champion for this? :( |
Pls. |
I want to retracted my against on Currently now I have working on idea to make a public namespace DoubleNumerics
{
public static class Vector2Tuple
{
public static double Distance(this in (double X,double Y) min,in (double X,double Y) max) => Math.Sqrt(min.DistanceSquare(max));
public static double DistanceSquare(this in (double X,double Y) min,in (double X,double Y) max)
{
var (x,y) = max.Remove(min).Pow(2);
return x + y;
}
public static (double X,double Y) Pow(this in (double X,double Y) value,double p) => (Math.Pow(value.X,p),Math.Pow(value.Y,p));
public static (double X,double Y) Add(this in (double X,double Y) left,in (double X,double Y) right) => (left.X + right.X,left.Y + right.Y);
public static (double X,double Y) Remove(this in (double X,double Y) left,in (double X,double Y) right) => (left.X - right.X,left.Y - right.Y);
public static (double X,double Y) Average(this in (double X,double Y) left,in (double X,double Y) right) => ((left.X + right.X) / 2,(left.Y + right.Y) / 2);
}
} This would be great if I could |
But then I would want namespace scoped aliases so that when I have a clash of class names. I can namespace BusinessLogic
{
global using User = Core.User
} And then everything underneath BusinessLogic will default to Core.User. But personally I am with @madelson and 100% believe that adding a simple type alias local to a file is the best approach and a step in the right direction. I believe For now worst case scenario you can do As a workaround you can always create a custom struct. using record types is a no go for me in a lot of cases, as it looks like its |
I just want to point out something I couldn't find in the discussion so far. This works: this doesnt (just for completenes)
and this would be really nice
So it feels a little like an oversight to me. |
This gets even more ironic when you use an even-simpler generic like using Foo = System.Nullable<(string Key, object Value)>;
class Bar
{
private Foo baz = ("A", new object());
private Foo qux = null;
} That said, since the language team seems to care more about records going forward, I'll probably just ignore tuples entirely from here on out. As long as something works 🤷🏼♂️. |
I am already championing the feature to address this :) |
(#4284 tracks the fact that Andy and Cyrus are championing this) |
I'm going to close this as a duplicate of #4284. |
@gafter commented on Mon Nov 07 2016
It has been requested that we support
@HaloFour commented on Mon Nov 07 2016
🍝 Generic version when combined with #3993?
@eyalsk commented on Mon Nov 07 2016
That's pretty cool!
@DavidArno commented on Wed Nov 09 2016
At first glance, this seems an excellent idea. But then it takes on the texture of "aerosol cream": it looks like rich, thick, real cream but turns out to be 90% air. Yes, it would be useful occasionally, but the scope would then just be within that file. Some means of giving it a wider scope would really make this useful, eg:
Subject.cs
OtherFile.cs
Update
Having thought though this topic, I now feel that @alrz's point re records is pertinent. There should be no need for tuple aliases when we have records. So I no longer think this a useful feature at all.
@dsaf commented on Tue Nov 08 2016
@DavidArno this was previously rejected for some reason #7451.
@DavidArno commented on Tue Nov 08 2016
@dsaf,
That's a shame, but thanks for the link.
@MgSam commented on Tue Nov 08 2016
I'm happy with the proposal as @gafter specified. I think generics and global scope are both orthogonal to this feature and should be considered separately.
@DavidArno commented on Tue Nov 08 2016
Generics and global scope are enhancements to the basic proposal. So you appear to be misusing the term "orthogonal" 😛
@MgSam commented on Tue Nov 08 2016
@DavidArno They are completely separable proposals that do not impact the merits of this feature as proposed. I'd call that orthogonal. Scope creep is the death of feature requests.
@qrli commented on Tue Nov 08 2016
I don't see this necessary. It is at best low priority.
If you want a type, define a type.
@alrz commented on Tue Nov 08 2016
Once we have records, it'll be a piece of cake.
I'd personally prefer to have generic and global type aliases over this.
@orthoxerox commented on Wed Nov 09 2016
@DavidArno records do not cover all the use cases you might need aliases for. See my example in #7453, there's no way a record can replace a long-winded generic interface type declaration.
@DavidArno commented on Wed Nov 09 2016
@orthoxerox,
Apologies, my comment wasn't clear. I was referring to this specific feature request: tuple aliases, not type aliases in general. I've updated my comment to fix that.
@alrz commented on Wed Nov 09 2016
@DavidArno I'm saying that when you want a named tuple you'd better to define a struct record. But generic and global type aliases are useful for other scenarios, regardless of this proposal.
@AdamSpeight2008 commented on Wed Nov 09 2016
Will the diposable form of using also be supported.
@alrz commented on Sat Nov 12 2016
@AdamSpeight2008 This is already supported:
Also see #9882 and #11420.
@AdamSpeight2008 commented on Sat Nov 12 2016
@alrz That's not what I'm asking.
Let's we have this function.
And it is call within the header of a using block.
Do the
Tuple<T,U>
dispose correctly the disposable items within the tuple? eg.Item1
,.Item2
@HaloFour commented on Sat Nov 12 2016
@AdamSpeight2008
#9882
@AdamSpeight2008 commented on Sat Nov 12 2016
@HaloFour If the tuple is decomposed into separate variables, we risk the chance of disposing of a copy.
@HaloFour commented on Sat Nov 12 2016
@AdamSpeight2008
That proposal goes over several potential implementations. Either way, this proposal is about
using
for aliases, notusing
for disposables. #9882 is aboutusing
for disposables and how that might relate to tuples, if at all.@jcouv commented on Sat Apr 08 2017
@gafter Should this be moved to csharplang?
@gafter commented on Sun Apr 09 2017
@jcouv yes, I'll move it.
The text was updated successfully, but these errors were encountered: