Spread operator like in es6 #2879
Replies: 13 comments 15 replies
-
You'll be able to do this with the proposed records: var bar = bar with { MyOtherIntProp = 4 }; but as @HaloFour pointed out, you can't do this though: var bar = foo with { MyOtherIntProp = 4 }; |
Beta Was this translation helpful? Give feedback.
-
I don't think "withers" covers anonymous classes or composing instances of new types from instances of other types. |
Beta Was this translation helpful? Give feedback.
-
I don't like how this leaves the order which the properties are evaluated up to the version of the compiler. Supposing you have this code:
Given this code, what order do the console writes happen?
|
Beta Was this translation helpful? Give feedback.
-
The pedantic answer is that none of them run because the code won't compile
(you're setting and returning _s in your int I property.
However, assuming that's not what you meant, I would assume the compiler
would be written to use _an_ order, but that would probably be alphabetical.
…On Thu, 10 Oct 2019, 17:11 Bill Barry, ***@***.***> wrote:
I don't like how this leaves the order which the properties are evaluated
up to the version of the compiler.
Supposing you have this code:
class Foo
{
string _s;
int _i;
public string S
{
get
{
Console.WriteLine("Foo.S_get");
return _s;
}
set
{
Console.WriteLine("Foo.S_set");
_s = value;
}
}
public int I
{
get
{
Console.WriteLine("Foo.I_get");
return _s;
}
set
{
Console.WriteLine("Foo.I_set");
_s = value;
}
}
}
class Bar
{
int _i;
string _s;
public int I
{
get
{
Console.WriteLine("Bar.I_get");
return _s;
}
set
{
Console.WriteLine("Bar.I_set");
_s = value;
}
}
public string S
{
get
{
Console.WriteLine("Bar.S_get");
return _s;
}
set
{
Console.WriteLine("Bar.S_set");
_s = value;
}
}
public int Baz { get; set; }
}
Given this code, what order do the console writes happen?
var bar = new Bar
{
...foo,
Baz= 4
};
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<https://github.com/dotnet/csharplang/issues/2879?email_source=notifications&email_token=ADIEDQKZEDAE7Q3PISDS633QN5H3BA5CNFSM4I7NU7DKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEA4447A#issuecomment-540659324>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ADIEDQKPU5CDWCVGGSHMTX3QN5H3BANCNFSM4I7NU7DA>
.
|
Beta Was this translation helpful? Give feedback.
-
I don't know what effect this operator has on JavaScript developers, but (on first inspection) it would seem to introduce a very fragile form of tight coupling between types. var bar = new Bar
{
MyStringProp = foo.MyStringProp,
MyIntProp = foo.MyIntProp,
MyOtherIntProp = 4
}; With the above code, any renaming of the properties of var bar = new Bar
{
...foo,
MyOtherIntProp = 4
}; On the other hand, the link between Renaming either Even worse, an innocent enhancement of foo - a new property on To me, this behaviour is inconsistent with the strongly typed nature of the C# language. |
Beta Was this translation helpful? Give feedback.
-
You would have the same problem using AutoMapper, but I think most of the programmers using it. |
Beta Was this translation helpful? Give feedback.
-
I think a proper implementation would not allow spread receiver to not have all spread object's properties. @damian2 you can also use reflection to achieve that: public static class SpreadExtension
{
public static TTarget Spread<TSource, TTarget>(this TTarget target, TSource source)
{
foreach (PropertyInfo sourceProp in typeof(TSource).GetProperties())
{
PropertyInfo targetProp = typeof(TTarget).GetProperty(sourceProp.Name);
targetProp.SetValue(target, sourceProp.GetValue(source));
}
return target;
}
} Usage: var bar = new Bar {
MyOtherIntProp = 4
}.Spread(foo); |
Beta Was this translation helpful? Give feedback.
-
I've worked with dozens of projects with AutoMapper and I can assure you debugging and reasoning about the code with implicit effects is not a pleasurable experience. IMO it's better to write a bit more but be able to easily see which property is used and which is not. I'm strongly against implicit assignments and mappings just because one has to spend one more minute to explicitly write them down. |
Beta Was this translation helpful? Give feedback.
-
@ronnygunawan I think you're missing the motivation for the syntactic sugar. @damian2 I think the motivation for this operator is poor. The saying goes, "Amateurs imitate, professionals steal."; the true motivation for this operator is best given in the dart language GitHub, introduced in Dart 2.3:
|
Beta Was this translation helpful? Give feedback.
-
I'm with you on that but, in my case, is not about "one minute" because, especially in LOB applications I end up with a lot of EntityFramework Now imagine that you'd like to add a property with the value from the current "request" and you have to inject it with some AutoMapper's voodoo. What I dislike the most, apart from writing a lot, is that this has to be done via reflection wasting resources for something that is known at compile time. But yes, I think that it can be fragile and needs to be well thougth and limited to specific use-cases. |
Beta Was this translation helpful? Give feedback.
-
I am not sure why this is not considered but the way TypeScript/Javascript dose it works well for immutability and with operator is just cumbersome. struct A could work like this |
Beta Was this translation helpful? Give feedback.
-
Correct me if I misunderstand the spread operator or if someone's already mentioned this I think one useful application of the spread operator in C# could be reducing something like this: public List<string> InsertList(List<string> secondList)
{
List<string> myList = new List<string>
{
"firstItem",
};
myList.AddRange(secondList);
myList.Add("lastItem");
return myList;
} into this: public List<string> InsertList(List<string> secondList)
{
return new List<string>
{
"firstItem",
...secondList,
"lastItem",
};
} Essentially an |
Beta Was this translation helpful? Give feedback.
-
If spread operator will be implemented, why not with some useful features (inspired by Dart): return new List<string>
{
"firstItem",
if (hasSecondItem) "secondItem", // only one-liner allowed
...thirdList, // list has type List<T>
...?thirdNullableList, // list has type List<T>?
for (var i in forthList) $"#{i}", // only one-liner allowed
for (var i in forthList) yield $"#{i}", // alternative syntax?
"lastItem",
}; |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
before:
after:
Beta Was this translation helpful? Give feedback.
All reactions