Was surprised to see that a C# Enum definition seems to allow an extra comma at the end (at least in VS2010).
e.g. :
public enum EnumTest1
{
Abc,
Def,
}
i.e. there is a comma at the end of "Def".
Just wondering if this is allowed by design, or is an oversight.
(This might be good to know, because if it is a bug, there may be no guarantees that code like the above will compile in future versions of C#).
It is allowed by design. Similarly, you can have trailing commas in initializers as well. For example:
var ints = new[] { 2, 3, 4, 3, };
var obj = new SomeClass { Prop1 = "foo", Prop2 = "bar", };
I think that allowing trailing commas makes creating auto-generated code much easier because you don't have to add last-in-the-list logic when outputting a list in your code.
Related
I have this code that checks the references of two variables,
I came across this case which is a bit confusing :
string first = "10";
object second = 10.ToString();
dynamic third = second;
Console.WriteLine($"{first == second} {first == third}");
The result is : False True
My first question is why are the first and third references equal? If the third variable is equal to the second it should be False because their object references aren't equal.
And I got confused when I changed the values to "1" like below:
string first = "1";
object second = 1.ToString();
dynamic third = second;
Console.WriteLine($"{first == second} {first == third}");
Then the result becomes: True True
Why does this happen?
I am not sure why it changes when you change it from 10 to 1
I believe this is an implementation detail and you should not rely on it (will try to find something in the specs) but some positive single digit numbers are cached in int.ToString implementation for .NET Core. Here is excerpt from UInt32ToDecStr which is called internally by int.ToString:
// For single-digit values that are very common, especially 0 and 1, just return cached strings.
if (bufferLength == 1)
{
return s_singleDigitStringCache[value];
}
As for equality - please check:
C# difference between == and Equals().
String interning in .Net Framework. (compiler will intern string literals, so all of them will point to the same address in memory)
Using type dynamic
UPD:
Was not able to find anything in specs, but next code behaves differently in .NET Framework and .NET 6 (former one prints 11 times False and the latter prints 10 times True and one False):
var dict = new Dictionary<int, string>()
{
{0, "0"},
{1, "1"},
{2, "2"},
{3, "3"},
{4, "4"},
{5, "5"},
{6, "6"},
{7, "7"},
{8, "8"},
{9, "9"},
{10, "10"},
};
foreach(var kvp in dict)
{
Console.WriteLine(object.ReferenceEquals(kvp.Key.ToString(), kvp.Value));
}
UPD2:
The caching was introduced for performance reasons by this PR and is mentioned in Performance Improvements in .NET Core 3.0 blogpost:
In some sizeable web applications, we found that a large number of strings on the managed heap were simple integral values like “0” and “1”. And since the fastest code is code you don’t need to execute at all, why bother allocating and formatting these small numbers over and over when we can instead just cache and reuse the results (effectively our own string interning pool)? That’s what PR dotnet/coreclr#18383 does, creating a small, specialized cache of the strings for “0” through “9”, and any time we now find ourselves formatting a single-digit integer primitive, we instead just grab the relevant string from this cache.
private int _digit = 4;
[Benchmark]
public string SingleDigitToString() => _digit.ToString();
Method
Toolchain
Mean
Error
StdDev
Ratio
Gen 0
Gen 1
Gen 2
Allocated
SingleDigitToString
netcoreapp2.1
17.72 ns
0.3273 ns
0.3061 ns
1.00
0.0152
–
–
32 B
SingleDigitToString
netcoreapp3.0
11.57 ns
0.1750 ns
0.1551 ns
0.65
–
–
–
–
The answer to the first question is because string equality isn't based on the object references, as reference types are by default.
first and third are both type string, even if only known at runtime, so the System.String's operator == override is called and:
...in turn, calls the static Equals(String, String) method, which performs an
ordinal (case-sensitive and culture-insensitive) comparison.
(source)
I'll also point out that Visual Studio provides a CS0253 compiler warning at first == second:
Possible unintended reference comparison; to get a value comparison,
cast the right hand side to type 'string'
As for the second question... See #GuruStron's answer.
I'm using ASP.NET Core 2.1. I have settings in appsettings.json and I bind them to classes using the options pattern. I want to override some of them in appsettings.Production.json.
Overriding is supported according to the docs, and works for me generally.
But it doesn't work for arrays.
appsettings.json:
"MySectionOuter": {
"MySectionInner": [
{
"foo": "1",
"bar": "2",
"baz": "3"
},
{
"foo": "a",
"bar": "b",
"baz": "c"
}
]
}
My overrides in appsettings.Production.json
"MySectionOuter": {
"MySectionInner": [
{
"bar": "4",
},
{
"baz": "d"
}
]
}
However that doesn't work - it adds rather than replaces.
I read that the array is syntactic sugar for a key-value store. So I also tried this:
"MySectionOuter": {
"MySection:1": {
"bar": "4",
},
"MySection:2": {
"baz": "b",
}
}
But that also doesn't work.
What is the correct syntax?
UPDATE
The comments show I haven't explained properly. What I want is like this:
During development:
element1: foo=1
element1: bar=2
element1: baz=3
element2: foo=a
element2: bar=b
element2: baz=c
During production:
element1: foo=1
element1: bar=2
element1: baz=4 // this was changed
element2: foo=a
element2: bar=b
element2: baz=d // this was changed
In fact, there are no arrays there when the configuration is built. It's just a key-value pair dictionary. So you end up with string keys, something like
"mysectionouter:mysectioninner:0:foo" = 1.
So when in your config you define an array, the following happens:
appsettings.json:
"mysectionouter:mysectioninner:0:foo" = 1
"mysectionouter:mysectioninner:0:bar" = 2
appsettings.production.json:
"mysectionouter:mysectioninner:0:bar" = new1
result:
foo = 1
bar = new1
So it's just index-based, and next configuration just overrides a key. In your second example, you achieve nothing but changing the index. Representation would be:
"mysectionouter:mysectioninner:1:bar" = new1
So back to your question: arrays are tricky in appsettings, and though supported, are generally hard and not intuitive to use.
By index you may get a weird merge of two not related objects, if you define different sets of settings in your files, like settings A and B in the first config, and C in second, you will get C and B in the result, and you likely don't want to have B at all. Worse still, you can get a mix of A and C if you define only some fields of each object.
I'd recommend using some other files for storing this kind of information. You can also break in the debugger just where the configuration is loaded and see for yourself how these keys are build to get more insight.
According to this blog post: https://www.paraesthesia.com/archive/2018/06/20/microsoft-extensions-configuration-deep-dive/
It's not possible to remove configuration items with a provider.
You can add configuration at override time, but you can’t remove things. The best you can do is override a value with an empty string.
Instead you should only fill as little information as needed in the appsettings.config and fill the appropriate settings in a more specialized settings file. E.g. appsettings.Development.config or your appsettings.Production.config. Or as suggested in the blog post:
Since you can’t remove things, specify as little configuration as possible and behave correctly using defaults in your code when configuration isn’t there.
I was actually having a similar issue in dotnet 6, when trying to merge arrays from multiple appsettings, when I stumbled across this thread.
The solution was actually way simpler then thought.
Microsoft.Extensions.Configuration merges arrays through the index:
{ foo: [1, 2, 3] } + { foo: [4, 5] } = { foo: 4, 5, 3 }
But we want to be able to declare which entries override others and which ones should be added to the list. And we do this by declaring a GUID as dictionary key instead of an array.
{
"foo": {
"870622cb-0372-49f3-a46e-07a1bd0db769": 1,
"cbb3af55-94ea-41a5-bbb5-cb936ac47249": 2,
"9410fcdc-28b3-4bff-bfed-4d7286b33294": 3
}
}
+
{
"foo": {
"cbb3af55-94ea-41a5-bbb5-cb936ac47249": 4,
"1c43fa78-b8db-41f8-809d-759a4bc35ee2": 5,
}
}
=
{
"foo": {
"870622cb-0372-49f3-a46e-07a1bd0db769": 1,
"cbb3af55-94ea-41a5-bbb5-cb936ac47249": 4, /*2 changed to 4 because key equals*/
"9410fcdc-28b3-4bff-bfed-4d7286b33294": 3
"1c43fa78-b8db-41f8-809d-759a4bc35ee2": 5, /*while 5 added to the list*/
}
}
This may seem inconventient at first, because one would think, that
((IConfiguration)config).GetSection("foo").Get<int[]>();
Throws some kind of invalid type exception, since a Guid is not what we know as array index.
But it can actually (implicitly!) return the merged "foo" section above as int[].
Why is this .NET enumeration allowed to have a comma in the last field?
Does this have any special meaning?
[FlagsAttribute]
public enum DependencyPropertyOptions : byte
{
Default = 1,
ReadOnly = 2,
Optional = 4,
DelegateProperty = 32,
Metadata = 8,
NonSerialized = 16,
}
It has no special meaning, just the way the compiler works, it's mainly for this reason:
[FlagsAttribute]
public enum DependencyPropertyOptions : byte
{
Default = 1,
ReadOnly = 2,
Optional = 4,
DelegateProperty = 32,
Metadata = 8,
NonSerialized = 16,
//EnumPropertyIWantToCommentOutEasily = 32
}
By comment request: This info comes straight out of the C# Specification (Page 355/Section 17.7)
Like Standard C++, C# allows a trailing comma at the end of an array-initializer. This syntax provides flexibility in adding or deleting members from such a list, and simplifies machine generation of such lists.
Also (to Nick Craver post) its much easier to add new enumerations.
This behaviour appropriate not uniquely to enums. Consider following:
var list = new int[] { 1, 2, 3, };
One other reason: It makes it easier to code gen.
I know that it is an old topic but, another approach that would make sense for this issue is for code versioning systems.
Consider the following example:
//version 1
var myArray = {
"item 1",
"item 2"
};
//version 2
var myArray = {
"item 1",
"item 2", //will be considered a change, it may be considered an erroneous approach
"item 3"
}
Now consider this approach:
//version 1
var myArray = {
"item 1",
"item 2",
};
//version 2
var myArray = {
"item 1",
"item 2", //will not be considered a change, it may be considered an erroneous approach too, but, means that the code wasn't changed intrinsically
"item 3",
};
Anyhow, both approaches may be considered incorrect or correct depending on the situation. I particularly prefer the second approach that makes much more sense when dealing with code versioning systems.
Anyway hope this helps.
Why add trailing commas
Why you should take advantage of this feature when writing code manually?
The resultant patches have less lines affected. This makes them easier to read and review.
Automatic merge and conflict resolution are more accurate because there isn't extra noise to confuse the algorithm.
Examples
Without trailing comma (okay)
Example of adding a line when the previous developer didn't leave a trailing comma:
## -119,7 +119,8 ## namespace SomeApp.Example
{
NameTitle = contact.NameTitle,
GivenName = contact.GivenName,
- FamilyName = contact.FamilyName
+ FamilyName = contact.FamilyName,
+ ProperName = contact.ProperName
},
ContactTelephone1 = contact.ContactTelephone1,
ContactType = contact.ContactType,
Without trailing comma (better)
Example of adding a line when the previous developer left a trailing comma:
## -122,2 +122,3 ## namespace SomeApp.Example
FamilyName = contact.FamilyName,
+ ProperName = contact.ProperName,
},
Note there is one line added in the latter vs one removed and two added. This is much easier for human and machine alike to deal with.
Why did they add it to C#?
As for why it is allowed, as per other answers:
The C# Specification (Page 355/Section 17.7) states:
Like Standard C++, C# allows a trailing comma at the end of an array-initializer. This syntax provides flexibility in adding or deleting members from such a list, and simplifies machine generation of such lists.
This applies to array initializers, object initializers and enums.
I have to make a function that returns the spells a character has.
So I have 3 parameters: a level (an int from 1-50), an enum representing a character class (only 8 classes) and an enum representing a race (3-4 races).
This function has to return an array with spell IDs. The higher the level, the more spells a character has.
What I did so far is hard-coded everything, but when I have to modify something it is a mess. I don't know what kind of data-structure best suits my needs without recurring to horrible ifs that are hard to change/mantain.
Also, the language is C# and I am using Xna/.NET 4.0
Update
public static int[] ListOfSpells(int level, CharacterClass chClass, CharacterRace chRace)
{
switch (chClass)
{
case CharacterClass.Mage:
return new int[] { 1, 2, 3 };
case CharacterClass.Knight:
return new int[] { 2, 5, 6 };
case CharacterClass.Paladin:
return new int[] { 3, 5, 6, 2 };
default:
return new int[] { };
}
}
// classes
public enum CharacterClass : short
{
Mage = 0x00,
Warlock,
Priest,
Monk,
Knight,
Assassin,
Paladin,
Hunter,
Warrior
}
// races
public enum CharacterRace : short
{
Human = 0x00,
Elf
}
A database if definitly what you need. You can maybe make it works with IEnumerable/Array now, but database will gave you the flexibility that you want for the future of your game.
I don't know what kind of data-structure best suits my needs without recurring to horrible
ifs that are hard to change/mantain.
A simple trivial array, alternativels a table in a database.
Fields:
Spell ID
Character
Class
Level
Description blablabla...
Then filter by matching condition.
And I suggest NOT returning an array - that is useless. make the method IEnumerable, then you CAN ToArray() it if needed, or just run along it.
I have a class, which its constructor is below
public GroupsForm(ref Dictionary<string, List<string>> groupsList)
I want to use the groupsList in other functions as well so I declared a private member in the class:
private Dictionary<string, List<string>> _groupsList;
But the problem is when I do _groupsList = groupsList; it makes a copy of the groupsList and changes made to _groupsList doesn't change groupsList, as I think it makes a deep copy by default. What I want is that it should point to that list.
In C++, this can easily be done via pointers, but can anyone tell me how can I do this in C#?
Ahmed has posted this image:
There are value types and reference types in C#. A dictionary is a reference type so whenever assigning a variable that holds a reference type to another, the reference is copied, which means that both variables will be holding the same data. So, if you change the data, you should expect it to change on both variables:
List<int> list1 = new List<int>() { 1, 2, 3 };
List<int> list2 = list1;
list2.Add(10);
list1.ForEach(x => Console.WriteLine(x)); // should print 1, 2, 3 and 10.
However, if you reassign the variable, then you are not changing the data:
List<int> list1 = new List<int>() { 1, 2, 3 };
List<int> list2 = list1;
list2 = new List<int>() { 10, 11, 12 };
list1.ForEach(x => Console.WriteLine(x)); // should print 1, 2, 3 only
One thing that caught my attention in your code though was that the constructor is expecting a ref. This means that you are passing the reference itself by reference, which in C++ would be something like a double pointer (type**). You'd do this if, in the snippet above, you want to have this effect:
void MethodA(ref List<int> list)
{
list = new List<int>() { 10, 11, 12 };
}
// ...
List<int> list1 = new List<int>() { 1, 2, 3 };
MethodA(ref list1);
list1.ForEach(x => Console.WriteLine(x)); // should print 10, 11, 12
One more thing -- AFAIK C# doesn't implement deep copies in any of it classes. You have to do it yourself.
In your InitGroups method, you've got an assignment statement to _groupsList - it's this new list that contains 3 items. You could change InitGroups to do something like:
var newGroups = (Dictionary<string, List<string>>)ser.ReadObject(reader,true);
foreach(var kvp in newGroups)
{
_groupsList.Add(kvp.Key,kvp.Value);
}
And then you'll still be working with the same Dictionary object.
You don't need the ref in your method signature. Objects are passed by reference anyway.
And no, there is no copying going on.
But the problem is when I do _groupsList = groupsList; it makes a copy of the groupsList
No, it does not. It copies a pointer. List is a reference type.
as I think it makes a deep copy by default
Think again. Your conclusion is wrong.
List<T> is a reference type, so all variables are pointers. Beginner C#, first week, first day, first hour. Go back and read the introduction then look for the error in the rest of your code you do not show us.
You are wrong on several points.
C# references are totally different from C++.
In short, you should not use ref here because it's for propagating assignments made to parameter to the calling code which is not what you mean.
You are wrong assuming there's any kind of copying involved here.
groupsList and _groups ist are two references pointing to the same object in memory.
You'll need to read more about reference and value types in C#.