C# Initializer Syntax - c#

For this class setup.
public class X
{
public Y YInstance;
public X()
{
YInstance = new Y();
}
}
public class Y
{
public long Z;
}
I had this code.
var x = new X();
x.YInstance.Z = 1;
Resharper had a hint to use object initializer which transformed my code to this.
var x = new X { YInstance = { Z = 1 } };
I'm familiar with normal object initialization using the brackets to fill out properties but I'm not sure what this is doing. Looking at the IL it doesn't appear to be setting YInstance with a new anonymous class which was my first guess. That would also not be the same functionality as before which would weird for Resharper to suggest.
I'm just looking for a language feature keyword to look up or a simple explanation.

Syntax is arbitrary, strictly speaking, but in my view the way to think about it is that YInstance = { Z = 1 } has no new keyword, so it's not calling any constructors. However, the initializer part of the syntax is present, so it's merely applying the initializer to the properties of a (hopefully!) existing YInstance. YInstance exists in your case because you created it in your X constructor. Here's what would happen if you didn't.
Instead of "Set YInstance to this thing", it's "Set the properties of YInstance to those things".
= { ... } in this case means to apply that initializer to the existing value of a property.
Indicating that with = between the property name and the initializer braces may not seem ideally intuitive at first, but it is what it is and like any syntax, you learn to recognize it soon enough. You can do the same to initialize the items of collections that have already been created:
public class C {
public List<int> Items { get; } = new List<int>();
}
...
// This can't be assigning to Items, because it's read-only
var c = new C { Items = { 0, 1, 2 } };
One of the C# team members (if you mention his name, he will appear) once kindly took the time to comment on an answer to a question about the list initializer syntax. They kicked it around a lot, but this was the best option they came up with. There are a lot of considerations when it comes to adding syntax to a mature language. They lose a lot of sleep over making it as clear as possible to the programmer, but at the same time it has to be unambiguous to the compiler, it can't break existing code, etc. "Syntax is arbitrary" doesn't mean that the C# team makes arbitrary decisions.
I can't say why Resharper would object to your taking arms against a sea of curly braces. I like your original version better.

Related

Should this list initializer behavior be reported as bug in the Visual Studio C# Compiler?

First of all I will say that I've changed my design and no longer need that but getting a good answer for that will still be nice
I have the following class, ListContainer, in my code (The attached codes are all mcve):
class ListContainer
{
public object ContainedList
{
get; private set;
}
public int Value
{
get; private set;
}
public ListContainer(object list, int value)
{
ContainedList = list;
Value = value;
}
}
And in some other class in my code I have a List<ListContainer> and I need each ListContainer to contain this List<ListContainer>, so I can implement it like that:
//Field in the class
List<ListContainer> mContainers = null;
//In the constructor:
mContainers = new List<ListContainer>();
mContainers.Add(new ListContainer(mContainers, SOME_CONST));
mContainers.Add(new ListContainer(mContainers, SOME_OTHER_CONST));
Than it works fine, but when I've tried to use list initializer:
//Field in the class
List<ListContainer> mContainers = null;
//In the constructor:
mContainers = new List<ListContainer>
{
new ListContainer(mContainers, SOME_CONST),
new ListContainer(mContainers, SOME_OTHER_CONST)
}
You would expect the results to be equivalent but in reality the result looks like that:
mContainers
[0] - ListContainer
ContainedList = null
Value = SOME_CONST
[1] - ListContainer
ContainedList = null
Value = SOME_OTHER_CONST
Seeing this results I've inspected the output MSIL of this C# compilation and seen the following code:
Now, this explains why the problem occurs, and I've even checked out in the CSharp Language Specification document and this is the defined behavior:
A List can be created and initialized as follows:
var contacts = new List<Contact> {
new Contact {
Name = "Chris Smith",
PhoneNumbers = { "206-555-0101", "425-882-8080" }
},
new Contact {
Name = "Bob Harris",
PhoneNumbers = { "650-555-0199" }
}
};
which has the same effect as
var __clist = new List<Contact>();
Contact __c1 = new Contact();
__c1.Name = "Chris Smith";
__c1.PhoneNumbers.Add("206-555-0101");
__c1.PhoneNumbers.Add("425-882-8080");
__clist.Add(__c1);
Contact __c2 = new Contact();
__c2.Name = "Bob Harris";
__c2.PhoneNumbers.Add("650-555-0199");
__clist.Add(__c2);
var contacts = __clist;
where __clist, __c1 and __c2 are temporary variables that are otherwise invisible and inaccessible.
So obviously this behaviour is intended. Is there a good reason everything is done on the temporary variable and not on the original one? since it seems like a wrong behaviour to me.
The reason is to avoid race conditions with concurrent threads accessing the original variable where you would add your elements. An inconsistency would appear if a thread accesses the variable while not all elements are added to it yet.
Two threads accessing the same variable would therefore get an inconsistent list, with different elements in it.
This would not come as a shock if the elements are added on different lines, but since you use an object initializer, it is normal to perceive the object as directly initialized with all its elements in it, hence the need of a temporary, invisible, variable.
Is there a good reason everything is done on the temporary List and not on the original one?
There is no original list:
var __clist = new List<Contact>();
// …
__clist.Add(__c1);
// …
__clist.Add(__c2);
var contacts = __clist;
Only one list is ever created. What you probably mean is that it’s done on a temporary variable instead of the original variable, but that has no practical effect—other than probably being easier to implement. This is especially true if you think about that collection initialization is not limited to the context of variable assignments:
SomeMethodCall(new List<int>() { 1, 2, 3 });
Since there is no reference to that list, the simplest solution to implement this is just to use a temporary variable that holds the list, and put that variable at the place of the initializer then.
What’s also important about this is that the old value is completely overwritten. So in your mContainers = new List<ListContainer>, the old value of mContainers is never being looked at for the purpose of the initializer syntax.
It’s probably a good idea to think about the collection initialization as an “atomic” operation. The list only exists (at least to you) once the whole initializer completes. So you cannot reference itself from within the initializer.
Assignments are first evaluated on the right side of the = and then the assignment takes place. So mContainers is still null.

Why is this Linq not working

I have a rather ugly object (yeah, I need the Tuple there :) ):
var roomToIndex = new Dictionary<RoomNode, Tuple<Int32, Dictionary<GrowDirections, Int32>>>();
I initialize this Dictionary like this:
for (var i = 0; i < roomsAdjacent.Count(); i++) {
roomToIndex.Add(roomsAdjacent.ElementAt(i), new Tuple<Int32, Dictionary<GrowDirections, Int32>>(i, new Dictionary<GrowDirections, Int32>()));
roomToIndex.ElementAt(i).Value.Item2.Add(GrowDirections.Top, 0);
roomToIndex.ElementAt(i).Value.Item2.Add(GrowDirections.Right, 0);
roomToIndex.ElementAt(i).Value.Item2.Add(GrowDirections.Bottom, 0);
roomToIndex.ElementAt(i).Value.Item2.Add(GrowDirections.Left, 0);
}
Where roomsAdjacent is a List of RoomNodes and GrowDirections a [Flags] Enumerable.
After those initialization steps I increment the Integer values of the 'inner' Dictionaries and at last I want to get the GrowDirection and RoomNode with the biggest value.
I try to do that the following way (now):
///Use the Counts to determine optimal FillDirection
var rDC = roomToIndex
///Select the RoomNode and the GrowDirection (incl. Count) with the highest Count for each Room
.Select(r => new { RoomNode = r.Key, Dict = r.Value.Item2.OrderByDescending(dirCount => dirCount.Value).ToList()[0] })
///Order those RoomNodes and GrowDirections descending
///Take the first Element and used the Dict's Key (GrowthDirection)
.OrderByDescending(rGI => rGI.Dict.Value).ToList();
var rDC0 = rDC[0];
if (rDC0.Dict.Key == GrowDirections.Top || rDC0.Dict.Key == GrowDirections.Bottom)
fillDirection = GrowDirections.Top | GrowDirections.Bottom;
else
fillDirection = GrowDirections.Right | GrowDirections.Left;
foreach (var rTI in roomToIndex.Where(rTI => rTI.Key != rDC0.RoomNode))
roomCellCount[rTI.Value.Item1] = 0;
The rDC has a Type of { RoomNode, Dictionary } and I have no Problem there.
But when I debug and step to the next line:
var rDC0 = rDC[0];
The debugger skips the line, goes right to the 'if statement' and throws an error, telling me that I got a NullReferenceException??!!
When I look at the values in my 'rDC object' there is no null-Value.
What can it be? Thank you for any tip/help :)
Examining your code the type of rDC is List<KeyValuePair<RoomNode, something very complicated>. The important thing is not something very complicated but that KeyValuePair<TKey, TValue> is a value type (struct). This means that List<KeyValuePair<TKey, TValue>> cannot have elements that are null. This means that rDC0 cannot be null. This is basically also what you tell us.
But then, if you get a NullReferenceException as you describe, it must be rDC0.Dict that is null. However, the Dict property cannot be null because it has very clearly been initialized to a new Dictionary<GrowDirections, Int32> by your initialization code.
So the code you have provided in the question should not be able to exhibit the behavior your describe. Either your code is somewhat different or the behavior you get is not exactly as you describe. The debugger problem you mention could be either a result of debugging the release version or symbols being out of sync with the executable code.
I suggest that you try one or more of the following things to fix your problem:
Rebuild the solution to make sure the debugger shows the correct source code when you debug
Switch to a debug build to turn off optimizations that will make debugging confusing
Break your data and code into smaller parts to get rid of the complicated and hard to understand code you have
The last suggestion is what will solve (or has solved) your problem. Let me just give you a few pointers:
Instead of using Dictionary<GrowDiretions, Int32> you could perhaps create a type with four properties which hopefully would make it more clear what your code is doing:
class GrowCounts {
public Int32 TopCount { get; set; }
public Int32 RightCount { get; set; }
public Int32 BottomCount { get; set; }
public Int32 LeftCount { get; set; }
public GrowDirections MaxGrowDirection {
get { // Return GrowDirections.Top if TopCount has the highest count etc. }
}
}
Instead of using new Tuple<T1, T2> use Tuple.Create to let the compiler infer the types of the tuple.
Do you really need the Tuple where the first element is an index? Some of your code uses for loops with Count and ElementAt and accessing collections in that way requires an index. However, maybe you could convert these loops into foreach loops and in the process you would discover that the index is unneeded. If that was possible you could get rid of the Tuple.
Apparently (according to what you wrote) it has to do with the the complex Linq statement, which had a side-effect that is somehow leading to the null reference error, which putting it in its own function contained. You might be able to get more clues about what exactly caused that, by seeing what happens if you put a simpler Linq Select statement before the initialization. See Martin's more comprehensive later suggestion about how you could track down what's actually going on here.

When to use var and when to use Strongly types? [duplicate]

This question already has answers here:
Use of var keyword in C#
(86 answers)
Closed 9 years ago.
I have class like below.
public class Dropdown
{
[Required(ErrorMessage = "Please select state")]
public string StateId { get; set; }
public List<SelectListItem> States
{
get
{
return new List<SelectListItem>()
{
new SelectListItem
{
Text = "State1",
Value = "S1",
Selected = false
},
new SelectListItem
{
Selected = false,
Value = "S2",
Text = "State2"
}
};
}
}
}
In Action Method, I have below two options while instantiating this class.
Approach 1
var d = new Models.Dropdown();
Approach 2
Models.Dropdown d = new Models.Dropdown();
Both are show same number of Methods/Properties/Data Members etc. I also heard that it is recommended to use Approach 1
Question
Is my assumption correct to use Approach 1 ?
The var keyword is compiler feature which allows implicit type declarations - I would opt to use var purely because it's shorter.
People will probably say you lose readability using var, however, what makes
MyClass myobj = new MyClass()
any more readable than
var myobj = new MyClass()
The only scenario where I do think it does make sense to use an explicit type is when declaring an interfaced type i.e.
IMyInterface myobj = new MyClass()
Or casting
MyBaseClass myObj = new MyClass()
Then again, you could argue those cases as well because the same code would be functionality equivalent
var myObj = (IMyInterface)new MyClass()
var myObj = (MyBaseClass)new MyClass()
In general, I very rarely see the need to explicitly define the type as it's inferred by the instantiated type.
Both are equivalent, in fact if you write #1 the compiler will resolve it to #2. What matters then is thee readability.
There is a long debate on why var should be avoided just because it has a negative impact on readability. My opinion is that it should be avoided when possible, however in extreme cases writing an explicit type for an expression could be just too cumbersome (just write a complicated linq expression with groupping or double groupping and try to write down its type).
There is no difference except for readability.
I'd pick Approach 1 because I consider it more readable.
for var the type is inferred. So there is no difference for both approaches from the type point of view.
As var is more readable, Stylecop suggests to use var whenever possible
Please have a look at this question to get the full information.

Can roslyn generate enums?

So, I feel like it's possible, but i don't have the chops to put it together. I have lookup tables (with ID and Name fields). I have enums that I keep in sync with the lookups. What I'd like is to make a list of SQL tables, and have roslyn create the enums during/before compile. this way I know my enums are always in sync, and it's one more thing off my plate.
Could someone out there show me the way, or tell me why it would be a bad idea? I feel like the solution isn't really a lot of code...
Thanks!
This is how you create enums with roslyn;
class Program
{
static void Main(string[] args)
{
var member1 = Syntax.EnumMemberDeclaration(
identifier: Syntax.Identifier("Member1")
);
var declaration = Syntax.EnumDeclaration(
identifier: Syntax.Identifier("MyEnum"),
modifiers: Syntax.TokenList(Syntax.Token(SyntaxKind.PublicKeyword)),
members: Syntax.SeparatedList(member1)
);
Console.WriteLine(declaration.Format());
Console.ReadLine();
}
}
this returns:
public enum MyEnum
{
Member1
}
Now to your question, I don't know if this is what you really need.
First I think there is not yet any built in functionality to do this at precompile, so you'd need to create a console exe and call it in your prebuild events.
So at this point probably it is a better idea to do this manually via code generation and not on every build, unless these tables are changing very frequently.
An in this case you don't really need roslyn to do it for you, you can just spit it out with any code generation software, or roll your own...
Here is some code updated for the current version of Roslyn and also shows adding attributes and values to the enum items.
public EnumDeclarationSyntax GenerateEnum()
{
var loanPurpose = new[]
{
"Business Launching",
"HomePurchase",
"HomeImprovement"
};
var enumDescriptions = new[]
{
"Launch a new business",
"Buy a home",
"Make home improvements"
};
var i = 0;
var members = new List<EnumMemberDeclarationSyntax>();
foreach (var item in loanPurpose)
{
var attribute = SyntaxFactory.Attribute(
SyntaxFactory.IdentifierName("Description"));
var attributeArgument = SyntaxFactory.AttributeArgument(
SyntaxFactory.LiteralExpression(
SyntaxKind.StringLiteralExpression,
SyntaxFactory.Literal(enumDescriptions[i ])));
attribute = attribute.WithArgumentList(
SyntaxFactory.AttributeArgumentList(
SyntaxFactory.SingletonSeparatedList(attributeArgument)));
var attributes = SyntaxFactory.SingletonList(
SyntaxFactory.AttributeList(SyntaxFactory
.SingletonSeparatedList(attribute)));
var objectCreationExpression = SyntaxFactory.EqualsValueClause(
SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression,
SyntaxFactory.Literal(i)));
var member = SyntaxFactory.EnumMemberDeclaration(attributes,
SyntaxFactory.Identifier(item),
objectCreationExpression);
members.Add(member);
i++;
}
var declaration = SyntaxFactory.EnumDeclaration
(new SyntaxList<AttributeListSyntax>(),
baseList: null,
identifier: SyntaxFactory.Identifier("LoanPurpose"),
modifiers: SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword)),
members: SyntaxFactory.SeparatedList(members)
);
return declaration;
}
The syntax for adding the attributes gets a little awkward but I find that I often need some attributes added. You probably already have the data for the attributes and values in the lookup tables driving the code generation.
The Answer provided by Sebastian 6 years ago likely used to work but no longer does.
New set of sample code to accomplish the same thing as of 18/12/2017
EnumMemberDeclarationSyntax member1 = EnumMemberDeclaration(identifier: Identifier("Member1"));
var members =new SyntaxNodeOrToken[]{member1};
var declaration = EnumDeclaration(
identifier: Identifier("MyEnum")).WithMembers(
members: SeparatedList< EnumMemberDeclarationSyntax>(members));

c# looping object creation

I'm very new with c#, and was previously attempting to ignore classes and build my small program structurally more similar to PHP. After reaching a road block, I'm trying to start over and approach the problem properly OO. I'm taking a long file, and in a loop, every time certain conditions are met, I want to make a new object. How can I have it create a new object, without having to specify a unique name?
Referral ObjectName = new Referral(string, string, int);
Secondly, once this is done, and the strings & int set their appropriate object properties, how can i unique-ify the class by one property, and then sort the class by another?
I'm sorry if these are basic questions, I have spent a large, large amount of time first trying to figure it out on my own with google, and a textbook. If only C# would allow multi-dimensional arrays with different types!
Thank you so much!
PS. I do mean to extract a list of unique objects.
All these answers, while helpful, seem to involve creating a shadow set of IEnumerables. Is there no way to do this with the class itself?
Trying the first solution, provided by Earwicker, adding each object to a List from within the loop, when I try to Write a property of the element to the console, i get the ClassName+Referral. What could I be doing wrong?--solved. still needed .property
still working. . .
C# does allow untyped arrays. All objects are derived ultimately from object, so you use an array or container of objects. But it's rarely necessary. How many types of object do you have?
Within the loop block, you can create an object exactly as you do in that line of code (except with the syntax fixed), and it will be a new object each time around the loop. To keep all the objects available outside the loop, you would add it to a container:
List<Referral> referrals = new List<Referral>();
// in the loop:
Referral r = new Referral(str1, str2, num1);
referrals.Add(r);
Suppose Referral has a numeric property called Cost.
referrals.Sort((l, r) => l.Cost - r.Cost);
That sorts by the cost.
For ensuring uniqueness by some key, you may find it easier to pick a more suitable container.
Dictionary<string, Referral> referrals = new List<Referral>();
// in the loop:
Referral r = new Referral(str1, str2, num1);
referrals[str1] = r;
This stores the referral in a "slot" named after the value of str1. Duplicates will overwrite each other silently.
First, you're going to need to spend some time familiarizing yourself with the basics of the language to be productive. I recommend you take a little time to read up on C# before getting in too deep - otherwise you'll spend a lot of your time spinning your wheels - or reinventing them :)
But here's some info to get you started.
Typically, in C# you create classes to represent elements of your program - including those that are used to represent information (data) that your program intends to manipulate. You should really consider using one, as it will make data manipulation clearer and more manageable. I would advise avoiding untyped, multi-dimensions array structures as some may suggest, as these rapidly become very difficult to work with.
You can easily create a Referall class in C# using automatic properties and a simple constructor:
public class Referall
{
// these should be named in line with what they represent...
public string FirstString { get; set; }
public string AnotherString { get; set; }
public int SomeValue { get; set; }
public Referall( string first, string another, int value )
{
FirstString = first;
AnotherString = another;
SomeValue = value;
}
}
You can add these to a dictionary as you create them - the dictionary can be keyed by which ever property is unique. Dictionaries allow you to store objects based on a unique key:
Dictionary<string,Referall> dict = new Dictionary<string,Referall>();
As you process items, you can add them to the dictionary:
Referall ref = new Referall( v1, v2, v3 );
// add to the dictionary, keying on FirstString...
dict.Add( ref.FirstString, ref );
If you need to sort items in the dictionary when you're done, you can use LINQ in C# 3.0:
IEnumerable<Referall> sortedResults =
dict.Values.OrderBy( x => x.AnotherString );
You can sort by multiple dimension using ThenBy() as well:
IEnumerable<Referall> sortedResults =
dict.Values.OrderBy( x => x.AnotherString )
.ThenBy( x => x.SomeValue );
List<Referral> referrals = new List<Referral>();
for (...)
{
referrals.Add(new Referral(string1, string2, number1));
}
Then, if you're using Linq (which I highly suggest), you can do this:
IEnumerable<Referral> sorted = referrals.OrderBy(x => x.string1).ThenBy(x => x.string2);
Otherwise, you can use the Sort() method on List<Referral>.
You can create an object without a reference, but you won't have any access to it later:
new Referral(string, string, int);
If you wish to put them in an array/list, these different types need to have a common base class. This is called polimorfism, which is a very important concept in OO programming.
You cannot ignore classes while using c#. Don't resist the change!
Do you really not need to create a class here? Do you really not need to give it a name? C# does allow loose typing, but type safety is a good thing.
I don't fully understand what you're trying to do. But maybe LINQ is what you're looking for. There's tons of documentation around, but as a quick 'teaser' have a look at the 101 Linq samples on MSDN
C# includes a wonderful feature called "iterator blocks". What you want to do is use the yield keyword to create an Enumerable of your Referal object, something like this (not that I'm making the file format and property names up, because you didn't share that):
public class Referral
{
public Guid id { get; private set; } // "uniquify"
public int ReferringId { get; set; }
public string ReferrerText { get; set; }
public string ReferrerDescription { get; set; }
private Referral()
{
id = new Guid();
}
private Referral(string Text, string Description, int ReferringId) : this()
{
this.ReferrerText = Text;
this.ReferrerDescription = Description;
this.ReferringId = ReferringId;
}
public static IEnumerable<Referral> GetReferrals(string fileName)
{
using (var rdr = new StreamReader(fileName))
{
var next = new Referrer();
int state = 0;
string line;
while ( (line = rdr.ReadLine() ) != null)
{
switch (state)
{
case 0:
next.ReferrerText = line;
state = 1;
break;
case 1:
next.ReferrerDescription = line;
state = 2;
break;
case 2:
next.ReferringId = int.Parse(line);
yield return next;
next = new Referral();
state = 0;
break;
}
}
}
}
}
Now you want to sort the referrals and presumable enumerate over them for some purpose. You can do that easily like this:
foreach (var referral in Referral.GetReferrals(#"C:\referralfile.txt").OrderBy( r => r.Text ) )
{
OutputReferral(referral);
}

Categories