I was wondering if there are any way to put break point inside an automatic constructor/object initializer block?
Example:
var x = new Person()
{
Name = 'John',
Age = DateTime.Now - Birthdate
}
I want to put breakpoint on the 4th line. This is very helpful when setting like 150 fields with different logic for each property and the type you are creating an instance of is not under your control (e.g. EF4 entity), therefore you cannot create a custom constructor. Any ideas?
A workaround you can use for this issue is writing the code like this to ease your debugging:
var x = new Person();
x.Name = "John";
x.Age = DateTime.Now - Birthdate;
Wrap the value on a line where you want a breakpoint in a self calling function:
var x = new Person() {
Name = new Func<string>(() =>"John").Invoke(),
Age = DateTime.Now - Birthdate
};
Now you will be able to "step into" it. It won't be of much use, though, as x will remain null until the end of the block.
If Name property is not automatic you can put a breakpoint inside set of that property.
If your doing it that way then you can't. You can out a breakpoint on the entire block and step through it using F11.
Why dont you do the following
Person p = new Person();
p.Name = "John";
p.//Blah
Related
This question already has answers here:
Using var or not using var [duplicate]
(3 answers)
Closed 4 years ago.
What is the "proper" way to use
var x = "text";
or
string x = "text";
Does it matter which I use? Is there a "standard" way people usually do it? I only ask because sometimes Rider suggests that I use var.
There are a few times where you must use an explicit type, and instances where you must use var.
Must use explicit type:
If you declare a variable without initializing it, or, if you want to initialize a variable explicitly as null
string myString;
int i;
string someString=null;
DateTime? nullableDate=null;
Must use var:
When you use an anonymous type, or a generic type with one or more type parameters that are anonymous types.
var stuff = new {Name="Bob", Age=25};
var bunchOfStuff = from item in items select new {item.Name, item.Age};
Otherwise
It's a question of style and/or taste
var is mostly syntactic sugar however there are times when you must use var and that's when you assign variables to anonymous types.
Anonymous type example:
var anonymousType = new { Name = "Mathew", DOB = DateTime.Now };
Console.WriteLine($"{anonymousType.Name} : {anonymousType.DOB}");
As far as when to use it otherwise... this is an opinion and or team guideline. There's nothing gained or lost doing it either way.
That said; here's my opinion.. this question will get put on hold for too broad but in the mean time here's a little something to look at however you choose.
I like var but I believe it can be confusing if you're not careful how you name / use variables but... personally I prefer var. It's shorter and can clean up code or make it somewhat shorter. Especially when you have somethin like Person person = new Person(); There's just too many Person's there for me... I also like how var mimics the syntax of JavaScript somewhat (although the two declarations are different).
var is not different than declaring the type out right so in your question string x or var x it doesn't matter. The compiler infers the type that is being assigned and that's what var becomes.
I do recommend this... When you declare ANY variables, especially those using var I would always name the declaration as close to the type as possible so that it doesn't matter which you choose. Name the variables correctly and no one should give you a hard time either way... Then again; this is all opinion.
var person1 = new Person();
Person person2 = new Person();
var employee1 = new Employee();
Employee employee2 = new Employee();
var employee3 = new Employee();
Person person3 = new Employee();
person1.Name = "Mathew";
person2.Name = "Mark";
employee1.Name = "Luke";
employee2.Name = "John";
employee3.Name = "Acts";
person3.Name = "Romans";
The documentation for var says:
An implicitly typed local variable is strongly typed just as if you had declared the type yourself, but the compiler determines the type.
In the end, there is functionally no difference. So, to answer your question, no, it doesn't matter which one you use. And it is for that very reason that there is no "standard" or "proper" one to use.
Use what you prefer.
class Program
{
static void Main(string[] args)
{
var people = new List<Person>
{
new Person { Name = "foo" },
new Person { Name = "bar" }
};
// ERROR: Left-hand side must be a variable, property, or indexer
people.FirstOrDefault(x => x.Name == "foo") = new Person();
}
}
public class Person
{
public string Name { get; set; }
}
Why is the above FirstOrDefault line not valid .NET code? If the return of FirstOrDefault() isn't a variable, what is it?
Edit: I understand how to make this valid .NET code - my point is trying to get a concrete answer as to why this is not valid. A definition from the docs perhaps as to why. I don't need to see how to make it correct :)
you cannot assign to the return of a function you need to store it in a variable
var person = people.FirstOrDefault(x => x.Name == "foo") ?? new Person();
FirstOrDefault is a Get method it is not an array indexer you cannot use it to set values, For instance what do you expect your original statement accomplish
people.FirstOrDefault(x => x.Name == "foo") = new Person();
you cannot use it for anything afterwards until it is in a variable.
A method returns used for returning values if you want to set in the method you must use an out parameter or reference, or a property.
Why is the above FirstOrDefault line not valid .NET code?
Because you can only assign a value to a variable, and FirstOrDefault doesn't return a variable.
If the return of FirstOrDefault() isn't a variable, what is it?
It's a value. You can store the result of FirstOrDefault in a variable, bit it isn't itself a variable
If you want to assign to the first element of the list, you should just access it at the index: people[0] = new Person().
To answer your other question, it's not a variable; it's an object. Imagine I tried to write "foo" = "bar". That would throw an exception -- what does it mean to assign a string literal to another? Your code is logically equivalent.
FirstOrDefault() is a method call and it cannot be used as a variable.
Answer to your question: the value of right hand side is assigned to left hand side, but an object cannot be on the left hand side; only a variable can.
You are trying to assign result of FirstOrDefault() method to People class constructor.
In C# (currently), you cannot set a value to a function call. Instead, you should say:
var person = people.FirstOrDefault(x => x.Name == "foo");
if (person != null) {
person = new Person();
}
The C# spec says that the = operator:
stores the value of its right-hand operand in the storage location, property, or indexer denoted by its left-hand operand and returns the value as its result (https://msdn.microsoft.com/en-us/library/sbkb459w.aspx)
A function call is not a storage location, property, or indexer.
This may sound confusing, but think about it this way:
The = operator is assignment. x = y means that, when you ask for x, give me y (remember basic algebra?).
You cannot say, "for this function, I want you to always give me y" (FirstOrDefault(x => x.foo) = y). That kinda goes against a function, which returns a result based on its definition! :)
I assume you're trying to retrieve person "foo" to do something with it later. You need to store it in a variable. Your code is not valid C# syntax.
class Program
{
static void Main(string[] args)
{
var people = new List<Person>
{
new Person { Name = "foo" },
new Person { Name = "bar" }
};
var fooPerson = people.FirstOrDefault(x => x.Name == "foo");
// Use fooPerson
}
}
in the code
people.FirstOrDefault(x => x.Name == "foo") = new Person();
we see an assignment statement. Assigning one value to another. Often with C style languages we call this assigning an lvalue (for left side) an rvalue (or right side.)
lvalue = rvalue.
There are limits on what the lvalue and rvalue can be. The rvalue must be able to be evaluated to the same type as the lvalue and the lvalue must be a location in memory (sometimes called a variable.)
If you want to find out more about these issues you can look at language references and how they talk about the lvalue and rvalue in assignment statements.
Purely curiosity at this point since the # fixed the problem I was having, but why is Name special?
I have an EF entity property called Name…if I don't put the # in front of Name, I don't get any kind of error, but the Name property on the object doesn't get assigned. If I put #Name in the object initializer, it assigns Name properly:
a = new Author
{
Id = Guid.NewGuid().ToString(),
#Name = "Jason Hater" // Apparently "Name" is quasi-reserved or something...?!?
};
I checked the generated code, and it's just named Name:
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=true)]
[DataMemberAttribute()]
public global::System.String Name
{
get
{
return _Name;
}
//...
}
So, Name isn't listed as a keyword, so why is it special?
Edit
Okay, as #sergey suggested, it's definitely a little more complicated than I first thought. Something goofy about Entity Framework specifically.
This is manifesting inside a unit testing class, that may be relevant also. I'm unsure what's relevant and what's not now unfortunately, so here's the whole [TestInitialize] method, and at the bottom of it you can see that the weirdness happens around context.SaveChanges():
[TestClass]
public class EntityConverterTests
{
private Author a;
private Post p, p2, p3;
[TestInitialize]
public void SetupEntities()
{
TestEntities context = new TestEntities();
// Clear it out!
foreach (Comment o in context.Comments) context.Comments.DeleteObject(o);
foreach (Post o in context.Posts) context.Posts.DeleteObject(o);
foreach (Author o in context.Authors) context.Authors.DeleteObject(o);
context.SaveChanges();
a = new Author
{
Id = Guid.NewGuid().ToString(),
Name = "Jason Hater"
};
context.Authors.AddObject(a);
System.Diagnostics.Debug.WriteLine(a.Name); // "Jason Hater"…Yay!
// probably irrelevant from here until context.SaveChanges()…?
p = new Post()
{
Title = "Linkbait!",
Author = a
};
p2 = new Post
{
Title = "Rant #1023",
Author = a
};
p3 = new Post
{
Title = "Polemic in E-flat minor #824",
Author = a
};
a.Posts.Add(p);
a.Posts.Add(p2);
a.Posts.Add(p3);
p.Comments.Add(
new Comment()
{
Body = "Nuh uh!",
Post = p
}
);
p.Comments.Add(
new Comment()
{
Body = "Yeah huh!",
Post = p
}
);
p.Comments.Add(
new Comment()
{
Body = "Third Reich.",
Post = p
}
);
p2.Comments.Add(
new Comment
{
Body = "I laughed, I cried!",
Post = p2
}
);
System.Diagnostics.Debug.WriteLine(a.Name); // "Jason Hater"…great!
context.SaveChanges();
System.Diagnostics.Debug.WriteLine(a.Name); // a.Name is null -> empty string!
}
// …
}
More coming, because now the # isn't "fixing" it--that is now I'm still seeing null in the test method I was seeing it correct before…something in another [TestMethod] may have been making a difference, perhaps…unsure, still investigating. Still, why is the change around context.SaveChanges() occurring?
Edit 2
Uh, okay…somehow the StoreGeneratedPattern property on my Name property was set to "Identity" in the modeling GUI. No idea how that happened. Changing it to "None" may have eliminated my problem. But…I know I hadn't changed that back when I thought the # symbol had fixed it…something still odd here.
Edit 3
One way or the other, the bad value for StoreGeneratedPattern was the cause of my assignment/saving problem. I'm unsure why I observed success one or more times with that setting, but the original question is no longer the correct question.
In C# the # is used if you want turn a keyword into an identifier. Since Name is no keyword, it has no effect at all.
This is purely a C# rule, at the IL level the # won't be present anymore, even if the name of the identifier matches a C# keyword. So it is impossible for Entity Framework to detect the difference.
"Why do I have to put # in front of Name in an object initializer?" - You don't, your problem is elsewhere as commenters have already suggested.
When performing a DbContext.SaveChanges the way that objects in the object graph get changed is when there is a StoreGeneratedPattern associated with a given property mapping.
Check to see if a StoreGeneratedPattern is associated with your Author.Name mapping.
For example, doing something like this:
foreach (DataRow row in data.Rows)
{
Person newPerson = new Person()
{
Id = row.Field<int>("Id"),
Name = row.Field<string>("Name"),
LastName = row.Field<string>("LastName"),
DateOfBirth = row.Field<DateTime>("DateOfBirth")
};
people.Add(newPerson);
}
Setting a breakpoint to an individual assignation is not possible, the breakpoint is set to the entire block.
If I want to see specifically where my code is breaking, I have to use:
foreach (DataRow row in data.Rows)
{
Person newPerson = new Person();
newPerson.Id = row.Field<int>("Id");
newPerson.Name = row.Field<string>("Name");
newPerson.LastName = row.Field<string>("LastName");
newPerson.DateOfBirth = row.Field<DateTime>("DateOfBirth");
people.Add(newPerson);
}
Or maybe I'm missing something. Can you properly debug when using an object initializer?
Object initializers are just syntactic sugar and get translated when they're compiled. Your original object initializer becomes something like this:
var temp = new Person();
temp.Id = row.Field<int>("Id");
temp.Name = row.Field<string>("Name");
temp.LastName = row.Field<string>("LastName");
temp.DateOfBirth = row.Field<DateTime>("DateOfBirth");
var person = temp;
Since the whole block is translated like that you can't break inside one step. If you absolutely need to break on one particular step, you have a few options.
Break it up. Don't use object initializers while debugging, and you can put them back afterwords.
Temp variables. Instead of assigning Id = row.Field<int>("Id") directly, assign row.Field<int>("Id") to a temp variable first (or whichever one you want to debug) and then assign the temp variable to the object initializer property.
Method call. You can wrap some of the code in a custom method call solely to allow you to add a breakpoint within your custom method. You could even generalize it like this:
Id = BreakThenDoSomething(() => row.Field<int>("Id"));
public static T BreakThenDoSomething<T>(Func<T> f)
{
Debugger.Break();
return f();
}
What exactly happens when adding an object to a collection such as List?
List<Person> people = new List<Person>();
Person dan = new Person() { Name="daniel", Age=10 };
people.Add(dan);
dan = new Person() { Name = "hw", Age = 44 };
When I execute the above code, the List<Person> peopledoes not get affected by final line.
So I am assuming that the list copies the references of the added object, so when change the reference, the list does not get affected. am I correct?
Well, the code you've shown doesn't actually add anything to the list at all. I assume you meant to have:
people.Add(dan);
in there somewhere?
But yes, the List<T> contains references to objects. It doesn't know about where the references have come from. It's worth being clear about the difference between a variable and its value. When you call:
people.Add(dan);
that copies the value of the argument expression (dan) in this case as the initial value of the parameter within List<T>.Add. That value is just a reference - it has no association with the dan variable, other than it happened to be the value of the variable at the time when List<T>.Add was called.
It's exactly the same as the following situation:
Person p1 = new Person { Name = "Jon" };
p2 = p1;
p1 = new Person { Name = "Dan" };
Here, the value of p2 will still be a reference to the person with the name "Jon" - the second line just copies the value of p1 to p2 rather than associating the two variables together. Once you understand this, you can apply the same logic to method arguments.
Well with that code the List<Person> people should not get affected by the 2nd line either.
Anyway, the List<Person> gets a reference if you use .Add() so if you modify that person later, the person in the list is "modified" too (it's the same person), but if you assign the person to someone else you're not affecting the reference, you're assigning the symbol to a new reference.
e.g.:
List<Person> people = new List<Person>();
Person dan = new Person() { Name="daniel", Age=10 };
people.Add(dan);
/* DanData = { Name="daniel", Age=10 };
* `people[0]` maps to "DanData"
* `dan` maps to "DanData" */
dan.Name = "daniel the first";
string dansNameInList = people[0].Name; /* equals "daniel the first" */
/* DanData = { Name="daniel the first", Age=10 };
* `people[0]` maps to "DanData"
* `dan` maps to "DanData" */
people[0].Name = "daniel again";
string dansName = dan.Name /* equals "daniel again" */
/* DanData = { Name="daniel again", Age=10 };
* `people[0]` maps to "DanData"
* `dan` maps to "DanData" */
dan = new Person() { Name = "hw", Age = 44 };
string dansNameInListAfterChange = people[0].Name /* equals "daniel again" */
string dansNameAfterChange = dan.Name /* equals "hw" */
/* DanData = { Name="daniel again", Age=10 };
* NewData = { Name = "hw", Age = 44 };
* `people[0]` maps to "DanData"
* `dan` maps to "NewData" */
To answer the original question, assuming you intended to add the person to the list before calling the third line:
Yes, the list only stores a reference to the object. In C#, ALL object variables are references.
So when you call new Person() a second time, the reference held by your variable dan is updated to point to the new instance. If the first instance has no reference pointed to it, it will be garbage collected in the next round. If you had added the first instance to the list, the list would still retain it's reference to the first instance.
It's important in .NET programming to have a good understanding of the difference between reference types and value types. This article provides a good overview:
http://www.albahari.com/valuevsreftypes.aspx
In this case, you created two Person objects (Daniel, age 10, and hw, age 44). It's the variables that reference the two objects that created the confusion.
Person dan = new Person() { Name="daniel", Age=10 };
Here, a local variable, dan, is assigned a reference to the newly created (Daniel, age 10) object.
people.Add(dan);
Here, the property people[0] is (indirectly via the List.Add method) assigned a reference to the existing (Daniel, age 10) object.
dan = new Person() { Name = "hw", Age = 44 };
Here, the local variable, dan, is assigned a reference to the newly created (hw, age 44) object. But the property people[0] still holds a reference to the existing (Daniel, age 10) object.
Adding at the end of your code
people[0] = dan;
would point to your new dan object.