I'm beginner when it comes to OOP. Yesterday I was trying to read some mvvm/wpf examples and of course I get into trouble... I have some problem with understand some of code below:
{
class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Addres { get; set; }
}
This is just normal Person class, nothing really unusal here. The problem is that I can't understand below code:
private void SayHi_Click(object sender, RoutedEventArgs e)
{
Person person = new Person
{
FirstName=FirstName.Text,
LastName=LastName.Text,
Addres=Address.Text
};
The part that I do not understand is:
Person person = new Person
{
FirstName=FirstName.Text,
LastName=LastName.Text,
Addres=Address.Text
};
I'm not sure what this is exactly. I thought that every new object should be initialized like this one: Class class = new Class();. Why there is no () after "new Person"? Instead of () we have {}. I know that we can use default, parameterized, static and private construcotrs. Could someone explain this to me? Similar situation in below tutorial from CodeProject:
http://www.codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial
We have a Song Class
public class Song
{
#region Members
string _artistName;
string _songTitle;
#endregion
#region Properties
/// The artist name.
public string ArtistName
{
get { return _artistName; }
set { _artistName = value; }
}
/// The song title.
public string SongTitle
{
get { return _songTitle; }
set { _songTitle = value; }
}
#endregion
}
And we have of course View Model for this class:
public class SongViewModel
{
Song _song;
public Song Song
{
get
{
return _song;
}
set
{
_song = value;
}
}
public string ArtistName
{
get { return Song.ArtistName; }
set { Song.ArtistName = value; }
}
}
And again, this part of code is something that I can't understand:
public class SongViewModel
{
Song _song;
public Song Song
What this "Song _song;" is? This is object of Song Class? And this Property "Song Song" is also wierd... Probably I have a lack of knowledge
I had to leave a new answer here, because I have seen 2 people get it wrong. The initializer syntax:
Person person = new Person
{
FirstName = FirstName.Text,
LastName = LastName.Text,
Address = Address.Text
};
Is not exactly equivalent to creating a new variable "person" and then assigning the properties. Rather, it is equivalent to creating a temp variable, assigning the properties, and then assigning the result to "person":
Person person;
var temp = new Person();
temp.FirstName = FirstName.Text;
temp.LastName = LastName.Text;
temp.Address = Address.Text;
person = temp;
The distinction can actually be quite important, especially working in a view model. You should be able to see this, if you imagine that you are assigning to a property whose setter raises the "PropertyChanged" event, which in turn has one or more view elements listening to it. Using the temp variable results in a big performance gain, because every event listener gets fired only once, rather than twice (once when the Person property is set, and then again when each of its properties are initialized).
The provided code is using an Object Initializer (MSDN)
From that page:
Object initializers let you assign values to any accessible fields or properties of an object at creation time without having to invoke a constructor followed by lines of assignment statements. The object initializer syntax enables you to specify arguments for a constructor or omit the arguments (and parentheses syntax).
Basically, it means you don't need the (), and can specify public field/property values in the {}.
Also; find a different site to learn MVVM. Directly creating Model/ViewModel objects from the UI is a big no-no.
This:
Person person = new Person
{
FirstName=FirstName.Text,
LastName=LastName.Text,
Addres=Address.Text
};
And:
Person person = new Person();
person.FirstName=FirstName.Text;
person.LastName=LastName.Text;
person.Addres=Address.Text;
Are equivalent. The first is syntactic sugar.
Related
I'm working with C#. I have a Employee class and I'm getting employee data from a URL then I created a list named EmpList in another class which is being populated with that information. I'm not getting the location of each employee so I want to hard code the location by making a set location function in Employee class.
The name 'EmpList' does not exist in the current context.
I've tried to make setLocation function in CreateEmpList function and I got no error but location was empty.
I know I'm probably doing something silly but I really need some help here. I really appreciate that.
Thankyou.
This is my employee class.
public class Employee
{
public string Name { get; set; }
public string Email { get; set; }
public Guid ID { get; set; }
public string Location { get; set; }
public void SetLocation()
{
foreach (var item in EmpList) // I'm getting error here
{
if (item.Email == "abc#gmail.com")
{
item.Location = "US";
}
}
And here I'm populating the list in another class.
private List<Employee> EmpList = null;
private void CreateEmpList(SPHttpClient client)
{
List<Employee> SortedList = new List<Employee>();
JObject jsondata = client.ExecuteJson(UriResources);
string strjsondata = jsondata.First.First.First.First.ToString();
JArray jsonArray = JArray.Parse(strjsondata);
foreach (var item in jsonArray) // Creating master resources list
{
ResourcesExcemptList.ForEach(i => i.ToLower());
if(!ResourcesExcemptList.Contains(item["ResourceEmailAddress"].
ToString().ToLower()))
{
if (Boolean.Parse(item["ResourceIsActive"].ToString()))
{
Employee emp = new Employee();
emp.ID = (Guid)item["ResourceId"];
emp.Email = item["ResourceEmailAddress"].ToString();
emp.Name = item["ResourceName"].ToString();
emp.Practice = item["ResourceGroup"].ToString();
emp.ApproverID =
(Guid)item["ResourceTimesheetManageId"];
SortedList.Add(emp);
}
}
}
EmpList= SortedList.OrderBy(o => o.Name).ToList();
//private void setLocation(){ }
}
The direct answer to your question
The main issue here is that you're not understanding how object oriented code works. You're not using this, and you seem to be confused when the class method will be executed and what that means.
Oddly, when in a class method, you still expect that you need to look through the list to find the correct object. That's the opposite of how you should approach it.
When an object's class method is being executed, you obviously already have found the object whose method you want to call. Because otherwise you wouldn't have been able to call that object's class method.
So what you need to do here is to iterate over the list before you call the object's class method, not after. Your Employee class:
public void SetLocation()
{
this.Location = "US";
}
And then:
private void CreateEmpList(SPHttpClient client)
{
// the rest of the code
EmpList = SortedList.OrderBy(o => o.Name).ToList();
foreach(var employee in EmpList)
{
employee.SetLocation();
}
}
Footnote
Your question shows a basic confusion on OOP principles, but the code itself shows a different level of grasp on OOP principles. I suspect that you didn't write this code yourself, but a colleague did.
I'm mentioning this because I noticed the comment in your example code:
//private void setLocation(){ }
Notice how its signature is that of a method definition, not that of a method call!
What I think has happened is that your colleague annotated the code and placed a reminder for you to create a method, and you've ended up implementing this method in the Employee class instead of in the other class (the one with the CreateEmpList method in it).
Creating the method in the other class makes a lot more sense than putting it in the Employee class. Something along the lines of:
public void SetLocation(Employee employee)
{
employee.Location = "US";
}
One possible solution, based on my comments:
Declare EmpList as:
public List<Employee> EmpList { get; private set;}
Then in your Employee class:
public void SetLocation()
{
var otherClassObj = new otherClassObj(); // Or perhaps some other way of getting the object of the other class.
otherClassObj.CreateEmpList(client); // You may have to change this.
foreach (var item in otherClassObj.EmpList)
{
if (item.Email == "abc#gmail.com")
{
item.Location = "US";
}
}
}
If your main concern is set location value and if empty then set hardcode value then consider this solution:
private string _location;
public string Location
{
get { return _location; }
set
{
if (string.IsNullOrEmpty(value))
{
_location = "US";
}
else
{
_location = value;
}
}
}
To answer your question: public void SetLocation(List<Employee> EmpList) allows the code inside SetLocation() to access the list object (passed by reference) but I doubt this is what you really want to do. (No offense;-)
Your logic isn't clear but surely within CreateEmpList(),
emp.Email = ...
if (emp.Email...) emp.Location = "..."
or within Employee, something like
public string Email { get {} set { Email = value; if (value...) Location = "..."; } }
It seems weird that you can define a class that has a member field that is of that class.
public class Person
{
public string Name { get; set; }
public Person Spouse { get; set; }
}
Now if I call that class:
var jane = new Person();
var jim = new Person();
jane.Spouse = jim;
jim.Spouse.Spouse = jane;
The last line causes an error. But I'm having a bit of trouble imaging what what the jim.Spouse.Spouse call is doing. It should evaluate jim.spouse first which is null so it causes an error right? If I assert jim.Spouse = jane first then it should work? But then I'm essentially saying jane.spouse = jane.
If a class has a field of the same type then what is it doing to the class? Is it just allowing two instances of the class to have a relationship? The class references itself so it's inheriting from itself? I'm kinda confused and also wondering if this is bad practice.
You've asked several things here, but in general it's fine to have a reference to the same type (even the same instance) on an object.
public class Thing {
private string name;
public Thing(string name) {
this.name = name;
}
public Thing Other {
get;
set;
}
public override string ToString() {
return this.name;
}
}
var o = new Thing("Foo");
o.Other = o;
Debug.WriteLine(o.Other.Other.Other.Other.ToString()); // Could go on forever
You're correct in your assertion about the exception. It throws because jim.Spouse is a null reference, so you can't set a property on it.
If you set jim.Spouse = jane;, then you should be able to set a reference. In this case you would want to say jim.Spouse.Spouse = jim;, since jim.Spouse evaluates to jane.
Regarding the fields of the same type, it's no different to anything else. It's just a variable with a type that the class uses. It is not an uncommon pattern for a type to have a reference to something else of the same type. For example, an Employee class might have a reference to a Manager, who is also an Employee. Another common example is tree implementations, in a binary tree a Node will have a reference to a Left/Right Child node.
Supposing I have an Album class :
public class Album
{
public string Name {get; set;}
public string Artist {get; set;}
public int Year {get; set;}
public Album()
{ }
public Album(string name, string artist, int year)
{
this.Name = name;
this.Artist = artist;
this.Year = year;
}
}
When I want to assign data to an object of type Album, what is the difference between the next 2 approaches :
Via Constructor
var albumData = new Album("Albumius", "Artistus", 2013);
or when instantiating
var albumData = new Album
{
Name = "Albumius",
Artist = "Artistus",
Year = 2013
};
Both approaches call a constructor, they just call different ones. This code:
var albumData = new Album
{
Name = "Albumius",
Artist = "Artistus",
Year = 2013
};
is syntactic shorthand for this equivalent code:
var albumData = new Album();
albumData.Name = "Albumius";
albumData.Artist = "Artistus";
albumData.Year = 2013;
The two are almost identical after compilation (close enough for nearly all intents and purposes). So if the parameterless constructor wasn't public:
public Album() { }
then you wouldn't be able to use the object initializer at all anyway. So the main question isn't which to use when initializing the object, but which constructor(s) the object exposes in the first place. If the object exposes two constructors (like the one in your example), then one can assume that both ways are equally valid for constructing an object.
Sometimes objects don't expose parameterless constructors because they require certain values for construction. Though in cases like that you can still use the initializer syntax for other values. For example, suppose you have these constructors on your object:
private Album() { }
public Album(string name)
{
this.Name = name;
}
Since the parameterless constructor is private, you can't use that. But you can use the other one and still make use of the initializer syntax:
var albumData = new Album("Albumius")
{
Artist = "Artistus",
Year = 2013
};
The post-compilation result would then be identical to:
var albumData = new Album("Albumius");
albumData.Artist = "Artistus";
albumData.Year = 2013;
Object initializers are cool because they allow you to set up a class inline. The tradeoff is that your class cannot be immutable. Consider:
public class Album
{
// Note that we make the setter 'private'
public string Name { get; private set; }
public string Artist { get; private set; }
public int Year { get; private set; }
public Album(string name, string artist, int year)
{
this.Name = name;
this.Artist = artist;
this.Year = year;
}
}
If the class is defined this way, it means that there isn't really an easy way to modify the contents of the class after it has been constructed. Immutability has benefits. When something is immutable, it is MUCH easier to determine that it's correct. After all, if it can't be modified after construction, then there is no way for it to ever be 'wrong' (once you've determined that it's structure is correct). When you create anonymous classes, such as:
new {
Name = "Some Name",
Artist = "Some Artist",
Year = 1994
};
the compiler will automatically create an immutable class (that is, anonymous classes cannot be modified after construction), because immutability is just that useful. Most C++/Java style guides often encourage making members const(C++) or final (Java) for just this reason. Bigger applications are just much easier to verify when there are fewer moving parts.
That all being said, there are situations when you want to be able quickly modify the structure of your class. Let's say I have a tool that I want to set up:
public void Configure(ConfigurationSetup setup);
and I have a class that has a number of members such as:
class ConfigurationSetup {
public String Name { get; set; }
public String Location { get; set; }
public Int32 Size { get; set; }
public DateTime Time { get; set; }
// ... and some other configuration stuff...
}
Using object initializer syntax is useful when I want to configure some combination of properties, but not neccesarily all of them at once. For example if I just want to configure the Name and Location, I can just do:
ConfigurationSetup setup = new ConfigurationSetup {
Name = "Some Name",
Location = "San Jose"
};
and this allows me to set up some combination without having to define a new constructor for every possibly permutation.
On the whole, I would argue that making your classes immutable will save you a great deal of development time in the long run, but having object initializer syntax makes setting up certain configuration permutations much easier.
Second approach is object initializer in C#
Object initializers let you assign values to any accessible fields or
properties of an object at creation time without having to
explicitly invoke a constructor.
The first approach
var albumData = new Album("Albumius", "Artistus", 2013);
explicitly calls the constructor, whereas in second approach constructor call is implicit. With object initializer you can leave out some properties as well. Like:
var albumData = new Album
{
Name = "Albumius",
};
Object initializer would translate into something like:
var albumData;
var temp = new Album();
temp.Name = "Albumius";
temp.Artist = "Artistus";
temp.Year = 2013;
albumData = temp;
Why it uses a temporary object (in debug mode) is answered here by Jon Skeet.
As far as advantages for both approaches are concerned, IMO, object initializer would be easier to use specially if you don't want to initialize all the fields. As far as performance difference is concerned, I don't think there would any since object initializer calls the parameter less constructor and then assign the properties. Even if there is going to be performance difference it should be negligible.
For some classes, ideally, I'd like to create special named instances, similar to "null." As far as I know, that's not possible, so instead, I create static instances of the class, with a static constructor, similar to this:
public class Person
{
public static Person Waldo; // a special well-known instance of Person
public string name;
static Person() // static constructor
{
Waldo = new Person("Waldo");
}
public Person(string name)
{
this.name = name;
}
}
As you can see, Person.Waldo is a special instance of the Person class, which I created because in my program, there are a lot of other classes that might want to refer to this special well-known instance.
The downside of implementing this way is that I don't know any way to make all the properties of Person.Waldo immutable, while all the properties of a "normal" Person instance should be mutable. Whenever I accidentally have a Person object referring to Waldo, and I carelessly don't check to see if it's referring to Waldo, then I accidentally clobber Waldo's properties.
Is there a better way, or even some additional alternative ways, to define special well-known instances of a class?
The only solution I know right now, is to implement the get & set accessors, and check "if ( this == Waldo) throw new ..." on each and every set. While this works, I assume C# can do a better job than me of implementing it. If only I can find some C# way to make all the properties of Waldo readonly (except during static constructor.)
Make a private class inside the Person that inherits the Person, ImmutablePerson : Person.
Make all the property setters locked up: override them with NotImplementedException for instance.
Your static Person initialization becomes this:
public static readonly Person Waldo = new ImmutablePerson("Waldo");
And static constructor may be removed, too.
Maybe you could have the following hierarchy:
class Person
{
protected string _name;
public virtual string Name{
get{
return _name;
}
}
}
class EditablePerson:Person
{
public new string Name{
get{
return _name;
}
set{
_name=value;
}
}
public Person AsPerson()
{
//either return this (and simply constrain by interface)
//or create an immutable copy
}
}
In my opinion the best is to return always a new instance on Waldo. This way the original Waldo will never be changed. But this will prevent you from using reference equality for comparison, therefore you will have to override Equals and GetHashCode.
Thanks to all your suggestions - Here is the solution. I needed to make string virtual, override the accessors in a public derivative class, and use a bool flag to permit modification.
It's important to note, that "name" is a reference type, and although I've prevented changing what "name" refers to, if it were something other than a string, such as a class that contains a self-modification method, it could still be possible to modify the contents of the object, despite having prevented modification to the object reference.
class Program
{
static void Main(string[] args)
{
Person myPerson = new Person("Wenda");
System.Console.WriteLine("myPerson is " + myPerson.name); // Prints "myPerson is Wenda"
if (myPerson == Person.Waldo)
System.Console.WriteLine("Found Waldo (first attempt)"); // doesn't happen
else
System.Console.WriteLine("Still trying to find Waldo..."); // Prints "Still trying to find Waldo..."
myPerson.name = "Bozo";
System.Console.WriteLine("myPerson is now " + myPerson.name); // Prints "myPerson is now Bozo"
myPerson = Person.Waldo;
if (myPerson == Person.Waldo)
System.Console.WriteLine("Found Waldo (second attempt)"); // Prints "Found Waldo (second attempt)"
System.Console.WriteLine("myPerson is " + myPerson.name); // Prints "myPerson is Waldo"
System.Console.WriteLine("Now changing to The Joker..."); // Prints "Now changing to The Joker"
try
{
myPerson.name = "The Joker"; // throws ImmutablePersonModificationAttemptException
}
catch (ImmutablePersonModificationAttemptException)
{
System.Console.WriteLine("Failed to change"); // Prints "Failed to change"
}
System.Console.WriteLine("myPerson is now " + myPerson.name); // Prints "myPerson is now Waldo"
Thread.Sleep(int.MaxValue); // keep the console alive long enough for me to see the result.
}
}
public class Person
{
public static readonly ImmutablePerson Waldo = new ImmutablePerson("Waldo");
public virtual string name { get; set; }
public Person() // empty base constructor required by ImmutablePerson(string) constructor
{ }
public Person(string name)
{
this.name = name;
}
}
public class ImmutablePersonModificationAttemptException : Exception
{ }
public class ImmutablePerson : Person
{
private bool allowMutation;
protected string _name;
public override string name
{
get
{
return _name;
}
set
{
if (allowMutation)
_name = value;
else
throw new ImmutablePersonModificationAttemptException();
}
}
public ImmutablePerson(string name)
: base()
{
allowMutation = true;
this.name = name;
allowMutation = false;
}
}
I was wondering what people thought of using properties as object initializers in C#. For some reason it seems to break the fundamentals of what constructors are used for.
An example...
public class Person
{
string firstName;
string lastName;
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
public string LastName
{
get { return lastName; }
set { lastName= value; }
}
}
Then doing object intialization with.....
Person p = new Person{ FirstName = "Joe", LastName = "Smith" };
Person p = new Person{ FirstName = "Joe" };
What you see here is some syntatic sugar provided by the compiler. Under the hood what it really does is something like:
Person p = new Person( FirstName = "Joe", LastName = "Smith" );
Person _p$1 = new Person();
_p$1.FirstName = "Joe";
_p$1.LastName = "Smith";
Person p = _p$1;
So IMHO you are not really breaking any constructor fundamentals but using a nice language artifact in order to ease readability and maintainability.
Object initializers does in no way replace constructors. The constructor defines the contract that you have to adhere to in order to create a instance of a class.
The main motivation for object initializers in the C# language is to support Anonymous Types.
var v = new { Foo = 1, Bar = "Hi" };
Console.WriteLine(v.Bar);
IMHO its sweet. Most objects are newed up with the default constructor, and must have some properties set before they are ready to run; so the object initializers make it easier to code against most objects out there.
Constructors should only really have arguments that are required to construct the object. Object initialisers are just a convenient way to assign values to properties. I use object initialisers whenever I can as I think it's a tidier syntax.
Since you're already using the new C# syntax, might as well use automatic properties as well, just to sweeten up your code a drop more:
instead of this:
string firstName;
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
use this:
public string FirstName { get; set; }
I think overall it is useful, especially when used with automatic properties.
It can be confusing when properties are doing more than get/set.
Hopefully this will lead to more methods, and reduce the abuse of properties.
Not your original question, but still...
Your class declaration can be written as:
public class Person
{
public string FirstName { get; set; }
public string LastName {get; set; }
}
and if it were my code, I'd probably have an object for Name with fields First and Last.
It's also quite necessary for projected classes returned from a language integrated query (linq)
var qry = from something in listofsomething
select new {
Firstname = something.FirstName,
Lastname = something.Surname
}
Adding to Nescio's thoughts - I'd suggest in code reviews actively hunting down expensive transparent operations in property accessors e.g. DB round tripping.
Object Initializers help to reduce coding complexity in that you don't need to create a half dozen different constructors in order to provide initial values for properties. Anything that reduces redundant code is a positive, in my book.
I believe the primary reason the feature was added to the language is to support anonymous types for LINQ.
If you want to enforce the use of a constructor, you could set your object's default parameterless constructor to private, and leave public only some enforced constructors:
public class SomeObject
{
private SomeObject()
{}
public SomeObject(string someString) //enforced constructor
{}
public string MyProperty { get; set; }
}
Using the above definition, this throws an error:
var myObject = new SomeObject { MyProperty = "foo" } //no method accepts zero arguments for constructor
Of course this can't be done for all cases. Serialization, for example, requires that you have a non-private default constructor.
I for one am not happy with them. I don't think they have a place in the constructor, or MS should got back and refactor them to allow you to use them in a private fasion. If I construct an object I want to pass in some PRIVATE data. I want it set from the outside world once and that's it. With Object Initializers you allow the values passed into the constructor to be modifiable.
Maybe in the future they will change this.