I'm a very new programmer and understand we want to minimize code redundancy so when we update we can make as few changes as possible and also minimize errors.
So I have a Student class that I want overloaded constructor so If I do back chaining it's like this.
public class Student
{
string name;
int Id;
public Student()
{
}
public Student(string name)
{
this.name = name;
}
public Student(string name, int Id) :this(name)
{
this.Id = Id;
But this is apparently bad because we want all the code in one constructor for what reason? Ease of reading?
public Student() : this(null, 0)
{ }
public Student(string name) : this(name, 0)
{ }
public Student(string name, int Id)
{
this.name = name;
this.Id = Id;
}
If I do this forward chaining then what happens if we add a new field like string major? If I do forward chaining then I create a new overloaded constructor with the added field. But now I have to change all the other constructors to call the new one. If I do backwards chaining I just create a new constructor and call the previous overloaded one.
public Student(string name, int Id, string major):this(name, Id)
{
this.major=major;
}
This seems like it follows OOP better but all examples in my text book show forward chaining and don't say why I shouldn't use back chaining.
If I used named/optional parameters it's even easier.
public Student(string name = null, int Id = 0, string major = null)
{
this.name = name;
this.Id = Id;
this.major = major;
}
And if I need another field I just have to edit the one and only constructor. This seems to follow OOP principles the best or am I mistaken? It at least eliminates code duplication the most. My assignment was to "implement the student class following the principles of OOP". I know all these are valid but is one way the best/accepted way of coding constructors? Are there shortcomings with named/optional params that I'm missing? As a beginner it's very confusing that there's so many ways to code this.
There is no best way, because they are different, each of them has advantages and disadvantages.
Independent constructors and chained constructors are available since C# 1.0, under most circumstances we use chained constructors but sometimes we have to use the former if the two constructors has totally different things to handle.
class Student
{
public Student()
{
DoSomething();
}
public Student(string name)
{
this.Name = name;
DoAnotherThing();
}
}
Comparing with optional parameters constructor, the above two are much longer, but to be honest, they are much safer. Consider the following case:
public class Student
{
public Student(string firstName = null, string lastName = null)
{
this.FirstName = firstName;
this.LastName = lastName;
}
public string FirstName { get; set; }
public string LastName { get; set; }
}
//it's working fine
//var danny = new Student("danny", "chen");
//as the business grows a lot of students need a middle name
public Student(string firstName = null, string middleName = null, string lastName = null)
{
this.FirstName = firstName;
this.MiddleName = middleName;
this.LastName = lastName;
}
//for a better sequence the programmer adds middleName between the existing two, bang!
Another difference between them is using reflection. Optional parameters will not generate more constructors for you, and the default values will not be applied if you are invoking the constructor using reflection.
I know all these are valid but is one way the best/accepted way of coding constructors?
Not to the best of my knowledge - you have many options. Your colleagues are the best people to talk to to reach a consensus. C# is becoming a very rich language, and that means that there will be many different ways to achieve the same thing.
Are there shortcomings with named/optional params that I'm missing?
Not to the best of my knowledge. Personally I think this is the best solution, but others may differ.
As a beginner it's very confusing that there's so many ways to code this.
Welcome to programming. There's millions of us programmers, and we're all busy adding complexity to the world!
I suggest looking deeper about this assumption :
"But this is apparently bad because we want all the code in one constructor for what reason"
There is Fluent Interface Pattern that puts these things apart, also I can not strongly argue that this directly translates for constructors.
customer
.NameOfCustomer("Shiv")
.Bornon("12/3/1075")
.StaysAt("Mumbai");
Illustrative implementation :
public class Customer
{
public string FullName { get; set; }
public DateTime DateOfBirth { get; set; }
public string Address { get; set; }
public Customer NameOfCustomer(string name)
{
this.FullName = name;
return this;
}
public Customer BornOn(DateTime dateOfBirth)
{
this.DateOfBirth = dateOfBirth;
return this;
}
public Customer StaysAt(string address)
{
this.Address = address;
return this;
}
}
Example source
This is a partial answer. Your "backwards chaining", with one constructor setting some parameter(s) then calling another constructor for the rest, is very reasonable/sensible for normal functions: one function does part of the work, then calls another function for some other work, and so on.
But for public constructors, any one of them can be called by client code, expecting to get a fully constructed object, fully initialized. Some constructors in your example leave members uninitialized (unless what you want is the default value for the type).
As an alternative, you can have private constructors.
Related
We went through structs at class and we've been tasked with creating a method inside the struct that changes the fields of an instance compared with another. For example, changing one's name if the other is a manager.
struct Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName
{
get => FirstName + LastName;
}
public int Age { get; set; }
public string Role { get; set; }
public double Salary { get; set; }
public bool IsManager { get; set; }
public static void EditInfo(ref Employee e1, ref Employee e2)
{
if (e1.IsManager)
{
Console.WriteLine($"Feel free to set {e2.FirstName}'s info: ");
e2.FirstName = Console.ReadLine();
e2.LastName = Console.ReadLine();
Console.WriteLine($"From now on thy name is {e2.FullName}!");
}
else if (e2.IsManager)
{
Console.WriteLine($"Feel free to set {e1.FirstName}'s info: ");
e1.FirstName = Console.ReadLine();
e1.LastName = Console.ReadLine();
Console.WriteLine($"From now on thy name is {e1.FullName}!");
}
}
}
Now, I have this gut feeling that my creation is terrible. I'm not sure about how to actually approach this at all, and it looks like a valuable lesson to learn for real business applications. I would appreciate every tip and trick that is necessary to make these methods, that interact with multiple instances of the struct, better.
Edit: Clarification
First you should make the mutable properties private set;, the constructor accept initial state, and make EditInfo an instance method. This more or less treats each Employee like a database record with access control, creating a simpler relationship.
public class Employee
{
public Employee(string firstName, string lastName, bool isManager, ...)
{
FirstName = firstName;
LastName = lastName;
IsManager = isManager;
// remaining properties...
}
public string FirstName { get; private set; }
public string LastName { get; private set; }
public bool IsManager { get; private set; }
// remaining properties...
public void Edit(Employee requester)
{
if (requester.IsManager) {
// query input from the user, make changes, and notify the user.
} else {
// notify the user that he doesn't have permission to edit this employee.
}
}
}
Using it thus becomes:
var manager = new Employee("Your", "Boss", isManager: true);
var sheep = new Employee("John", "Doe", isManager: false);
sheep.Edit(manager); // Essentially says "edit sheep using manager as permission".
Secondly, unless your instructor forbade you from using class, you should make it a class and get rid of all the ref declarations. struct and ref are very useful in the right cirumstances, but unless you're aware of the tradeoffs and code rigorously, its too easy to introduce a bug that will be difficult to reason about considering your experience level.
Classes don't automatically make copies or require the ref keyword. Structs on the other hand do make copies without ref, thus semantically requiring(but not enforcing) it at every call site that makes modifications to it. This has further implications which you may not be aware of. Consider properties. Properties cannot be passed with ref, only locals, fields, and array elements. Unfortunately that means it's currently impossible to pass a struct property by ref(though subject to change in a future C# version). This will likely bite you down the road.
In summary, prefer classes in C# unless you have a good reason to use structs(i.e. GC performance, very special purpose types). Above all, aim for readability.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
I was thinking about language constructs and how when we talk about classes and objects in Object oriented languages we draw comparisons to real world. Like when people talk of Inheritance people would quote an example of Parent and Children. One thing that i don't find in OO languages that i know , mainly C, C++, C#, is that they don't have a mechanism to declare a property as mandatory. What i mean by that is I cannot define a class called human and say that face, hands and lets say eye are mandatory property of my class. By having that construct i can enforce that anyone who is using my class need to set those properties before using my class. If user forgets to set those properties then i should get an compile time error.
Just wanted to see community thoughts on that.
Here is reason why i had asked above question:
When i build my user controls, i want to make sure that users should set some of the properties in their code when they use my control. For example, lets say i build a customer user control that would be used by other developers in my team. Some of the properties that i have exposed are: "CustomerId", "FirstName", "LastName", "Address1", "City", "State" and ZipCode. Now i want to make sure that any consumer of my control should set "CustomerId". Using Constructor to enforce that the value is set is a way but it will throw a run time exception plus how would user call that constructor from .cs file without dynamically creating the control and adding it to control collection.
You can do that, with a DDD principle: create a class with a private default constructor, and a public constructor that accept required parameters and validate its values. If a value is invalid, throw an exception so that the object cannot be created. Properties could also have private setters instead of public setters.
You can also create a 'Mandatory' attribute and put those on top of the properties that are mandatory; and have a mechanism that checks this based on whether a property has been decorated with the attribute or not.
Example:
public class BlogEntry
{
private BlogEntry() {}
public BlogEntry(string title, string body)
{
LastModifiedDate = DateTime.Now;
Title = title;
Body = body;
var blogEntryValidator = new BlogEntryValidator();
blogEntryValidator.ValidateAndThrow(this);
}
public int Id { get; private set; }
public string Title { get; private set; }
public string Body { get; private set; }
public DateTime? LastPublishDate { get; private set; }
public DateTime LastModifiedDate { get; private set; }
public virtual ICollection<Comment> Comments { get; private set; }
public void Publish()
{
LastPublishDate = DateTime.Now;
}
public void Unpublish()
{
LastPublishDate = null;
}
public void Modify(string title, string body)
{
Title = title;
Body = body;
LastModifiedDate = DateTime.Now;
}
public Comment AddComment(string commentText, string emailAddress, string name)
{
var comment = new Comment(this, commentText, emailAddress, name);
if (Comments == null) Comments = new List<Comment>();
Comments.Add(comment);
return comment;
}
public void RemoveComment(Comment comment)
{
Comments.Remove(comment);
}
}
public class Comment
{
private Comment() {}
public Comment(BlogEntry blogEntry, string name, string emailAddress, string commentText)
{
BlogEntry = blogEntry;
Name = name;
EmailAddress = emailAddress;
CommentText = commentText;
DateWritten = DateTime.Now;
var commentValidator = new CommentValidator();
commentValidator.ValidateAndThrow(this);
}
public int Id { get; private set; }
public string Name { get; private set; }
public string EmailAddress { get; private set; }
public string CommentText { get; private set; }
public DateTime DateWritten { get; private set; }
public BlogEntry BlogEntry { get; private set; }
}
Yes, C++ and C# allow for this via constructors.
class A
{
public:
A(int x, int y, int z)
: _x(x_, _y(y), _z(z) {}
private:
int _x;
int _y;
int _z;
};
You cannot create an instance of A without providing values for _x, _y, and _z.
The reason is that state needed to fulfil class invariants should be provided during object construction, so you should provide values of 'mandatory' properties as constructor parameters. Your question is based on false assumption that an object is characterized by setting state with properties. This is wrong for a handful of reasons, some of which are:
many, if not most OO languages have no properties: Java, C++,...
what you use is only formally an object, it is actually a plain record and it is not very object oriented, same as e.g. C++ struct without methods (see notes at the bottom about setters vs methods)
Allowing the client to create instances of the objects which are only later set up with correct values for mandatory state is sure-fire way to spend many hours in company of debugger.
Let's take some User with invariant that first and last name must always be set.
class User {
public User(string first, string last) { ... }
public User(string first, string last, uint age) : this(first, last) { ... }
}
// client code:
var user = new User("john", "doe");
var user2 = new User("Clint", "Eastwood", 82);
Compiler ensures that no one can instantiate the object without fulfilling the invariants.
Now compare it with your approach:
class User {
public User(string first, string last) { ... }
public User(uint age) { ... }
[Mandatory] public string FirstName { get; set; }
[Mandatory] public string LastName { get; set; }
}
// client code:
var actor = new User(82); // << invalid
actor.FirstName = "Clint";
actor.LastName = "Eastwood"; // << valid
This approach results in more code and allows for a period of time (between << invalid and << valid) where your object is not in a valid state. What if some of property setters throw an exception? You are left with broken object instance floating around. Do you expect the compiler to also verify that code in the setter can not throw? Do you think it is even possible? Besides that, every client which instantiates User instances must check what are the mandatory properties and make sure to set all of them. This effectively breaks encapsulation.
IMO, property setters should be rare, unlike getters. I believe that in such a class you should not have setters for FirstName/LastName, only getters. Instead there should be a method SetName(string first, string last) if you really want to allow name changing. Here's why:
// lets rename actor
actor.FirstName = "John";
actor.LastName = "Wayne";
If the last line throws, you are left with John Eastwood, an actor I have never heard about. With actor.SetName("John", "Wayne") this can't happen.
Additionally, what about property which have dependency in order you specify them, e.g.
obj.ErrorCode = 123; // imagine that error code must be != 0
obj.ErrorMsg = "foo"; // in order to be allowed to set error code
Would you also introduce attributes for that instead of having obj.SetErrorInfo(123, "foo")? This makes it obvious that properties break encapsulation as the order is caused by the implementation detail, unlike with method call.
Quite often, in languages like C#, required state or dependencies is provided in constructor while optional state can be set through properties. However, it is not properties or inheritance which make a language object-oriented.
Sure you can! Just use parameters in constructor to denote which are mandatory.
public class Human
{
public Face Face { get; set; }
public Hand Hand { get; set; }
public Human(Face face, Hand hand) {} etc...
}
In this instance, you cannot use the private constructor, so these properties are essentially "mandatory" in order to use the Human class.
I'm having a hard time trying to figure out the meaning of this advice from Attribute Usage Guildelines:
Do not define a parameter with both named and positional arguments. The following code example illustrates this pattern.
And the code is:
public class NameAttribute: Attribute
{
string userName;
int age;
// This is a positional argument.
public NameAttribute (string userName)
{
this.userName = userName;
}
public string UserName
{
get
{
return userName;
}
}
// This is a named argument.
public int Age
{
get
{
return age;
}
set
{
age = value;
}
}
}
Now, I'm sorry if it's really simple and I am wasting your time. But I just don't understand the meaning and what example demonstrates. The fact that English is not my native language might be a factor, but I didn't experience any difficulties reading MSDN before. I also tried to read the translated version of this article, but it makes even less sense to me.
So, if someone would be kind enough to rephrase and explain it to me, that would be really helpful. If you can also explain why MSDN advises to do so, I'm all ears.
Think about how you would have to use such an attribute:
[Name("Jack", Age = 25)]
public class ClassToDecorate { }
Now, this doesn't look all that clear because two styles are being mixed: UserName is being set via the attribute's constructor ("positional"), but Age is being explicitly set as a property ("named").
The guideline is suggesting that it would be better to redesign the attribute such that exactly one of the following decorations would work:
[Name("Jack", 25)] // Positional only
(or)
[Name(UserName = "Jack", Age = 25)] // Named only
I think you are the victim of a crummy example, it doesn't actually demonstrate the problem. A better example of doing it wrong is adding this constructor:
public NameAttribute (string userName, int age)
{
this.userName = userName;
this.Age = age;
}
Now the client code could use the attribute this way:
[Name("foo", 42)]
and this way:
[Name("foo", Age = 42)]
Both are equally valid, the client programmer won't be able to make up his mind which one to choose. A much nastier example would be this constructor:
public NameAttribute(int age) {
this.userName = "unspecified";
this.Age = age;
}
which allows:
[Name(42, Age = 43)]
I'm trying to build a class which will initalise its self either by passing in a reference to a record in a database (with the intention that a query will be run against the database and the returned values for the objects properties will be set therein), or by specifying the values "by hand" - this no database call is required.
I've looked at a couple textbooks to discover the "Best-practice" for this functionality and sadly I've come up short.
I've written a couple sample console apps reflecting what I believe to be the two most probable solutions, but I've no Idea which is the best to implement properly?
Sample App #1 uses what most books tell me is the "preferred" way but most examples given alongside those claims do not really fit the context of my situation. I'm worried in here that the flow is not as readable as App #2.
using System;
namespace TestApp
{
public class Program
{
public static void Main(string[] args)
{
var one = new OverloadedClassTester();
var two = new OverloadedClassTester(42);
var three = new OverloadedClassTester(69, "Mike", 24);
Console.WriteLine("{0}{1}{2}", one, two, three);
Console.ReadKey();
}
}
public class OverloadedClassTester
{
public int ID { get; set; }
public string Name { get; set; }
public int age { get; set; }
public OverloadedClassTester() : this(0) { }
public OverloadedClassTester (int _ID) : this (_ID, "", 0)
{
this.age = 14; // Pretend that this was sourced from a database
this.Name = "Steve"; // Pretend that this was sourced from a database
}
public OverloadedClassTester(int _ID, string _Name, int _age)
{
this.ID = _ID;
this.Name = _Name;
this.age = _age;
}
public override string ToString()
{
return String.Format("ID: {0}\nName: {1}\nAge: {2}\n\n", this.ID, this.Name, this.age);
}
}
}
This Sample (App #2) "appears" more readable - in that I think it's easier to see the flow of operation. However it does appear efficient in terms of characters saved :p. Also, is it not dangerous that it calls a method of the object before it's fully initialised, or is this not a concern?
using System;
namespace TestApp
{
public class Program
{
public static void Main(string[] args)
{
var one = new OverloadedClassTester();
var two = new OverloadedClassTester(42);
var three = new OverloadedClassTester(69, "Mike", 24);
Console.WriteLine("{0}{1}{2}", one, two, three);
Console.ReadKey();
}
}
public class OverloadedClassTester
{
public int ID { get; set; }
public string Name { get; set; }
public int age { get; set; }
public OverloadedClassTester()
{
initialise(0, "", 21); // use defaults.
}
public OverloadedClassTester (int _ID)
{
var age = 14; // Pretend that this was sourced from a database (from _ID)
var Name = "Steve"; // Pretend that this was sourced from a database (from _ID)
initialise(_ID, Name, age);
}
public OverloadedClassTester(int _ID, string _Name, int _age)
{
initialise(_ID, _Name, _age);
}
public void initialise(int _ID, string _Name, int _age)
{
this.ID = _ID;
this.Name = _Name;
this.age = _age;
}
public override string ToString()
{
return String.Format("ID: {0}\nName: {1}\nAge: {2}\n\n", this.ID, this.Name, this.age);
}
}
}
What is the "correct" way to solve this problem, and why?
Thanks,
I would definitely chain the constructors, so that only one of them does the "real work". That means you only have to do the real work in one place, so if that work changes (e.g. you need to call some validation method at the end of the constructor) you only have one place where you need to change the code.
Making "simple" overloads call overloads with more parameters is a pretty common pattern IME. I find it more readable than the second version, because you can easily tell that calling one overload is going to be the same as calling the "bigger" one using the default values. With the second version, you have to compare the bodies of the constructors.
I try not to have more than one constructor which chains directly to the base class wherever possible - unless it's chaining to a different base class constructor, of course (as is typical with exceptions).
Do not use database calls in a constructor. This means your constructor is doing a lot of work. See http://misko.hevery.com/code-reviewers-guide/ (Google guide for writing testable code).
Apart from this, chaining constructors (option 2) looks good. Mostly because as you say it is readable. But why are you assigning this.Name etc in the constructor and doing it again in initialize. You could assign all values in initialize.
Maybe something like this?
public class OverloadedClassTester
{
public int Id { get; private set; }
public string Name { get; private set; }
public int Age { get; private set; }
public OverloadedClassTester (Person person)
: this (person.Id, person.Name, person.Age) { }
public OverloadedClassTester(int id, string name, int age)
{
Id = id;
Name = name;
Age = age;
}
public override string ToString()
{
return String.Format("Id: {0}\nName: {1}\nAge: {2}\n\n",
Id, Name, Age);
}
}
maybe it would be better to use optional parameters? In this case, you would create a single constructor and initialize the values to the parameters you wish to set.
More information: link text
I prefer #1, the chaining constructors, from a maintenance perspective. When someone comes back to edit the code later on, you wouldn't want them to edit the initialise() method and not realize that it is being called from a constructor. I think it is more intuitive to have all the functional parts in a constructor of some kind.
Personally, I use constructor chaining like that all the time.
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.