Which method style is better?
Is it generally bad practice to modify the variable within a method?
public class Person
{
public string Name { get; set;}
}
//Style 1
public void App()
{
Person p = new Person();
p.Name = GetName();
}
public string GetName()
{
return "daniel";
}
//Style 2
public void App()
{
Person p = new Person();
LoadName(p)
}
public void LoadName(Person p)
{
p.Name = "daniel";
}
There are times when both styles may make sense. For example, if you're simply setting the name, then perhaps you go with the first style. Don't pass an object into a method to mutate one thing, simply retrieve the one thing. This method is now more reusable as a side benefit. Think of it like the Law of Demeter or the principle of least knowledge.
In other cases, maybe you need to do a wholesale update based on user input. If you're displaying a person's attributes and allowing the user to make modifications, maybe you pass the object into a single method so that all updates can be applied in one spot.
Either approach can be warranted at different times.
I think the code is more clear and readable when methods don't change objects passed. Especially internal fields of passed object.
This might be needed sometimes. But in general I would avoid it.
Updated based on comment (good point)
I agree with Anthony's answer. There are times when both styles may make sense.
Also, for more readability you can add the LoadName function in person class.
public void App()
{
Person p = new Person();
p.LoadName(); //If you need additional data to set the Name. You can pass that as Parameter
}
You are accessing the data using properties which technically is by a methods. What you are worried is property accessing iVar or internal variable. There reason why it is generally bad to allow access of iVar is because anyone can modify the variables without your knowledge or without your permission, if its through a methods (properties), you have the ability to intercept the message when it get or set, or prevent it from getting read or write, thus it is generally said to be the best practice.
I agree with Ron. Although your particular example could be slightly contrived for posting reasons, I would have a public getter for Name, and a private setter. Pass the name to the constructor, and the Name property will get set there, but afterwards can no longer be modified.
For example:
public class Person
{
public string Name { get; private set; }
public Person( string name)
{
Name = name;
}
}
Related
I am making a constructor for a class in c#, and I would like it to fill its values differently depending on the type of class that called it.
For example, there is a class called Employer and a class called Person.
When an instance of Employer calls new Person(); I would like the constructor in Person to set the new person's Employed variable to true.
Is this possible in c#?
Tried searching for an answer but was unsure how to word the question.
You can't do it automatically, no. (You could grab a stack trace and parse that, but it would be horribly brittle in the face of JIT compiler optimizations etc.) I'd argue that doing so would make the code brittle and hard to maintain, too - the effect would be like "spooky action at a distance".
The simplest option is to add a bool employed parameter in the constructor instead. Then it's really obvious at every call site how you want the constructed object to behave.
There are a few different ways to do this. The first is to overload the constructor.
public Person() {
this.Employed = false;
}
public Person(bool employed) {
this.Employed = employed;
}
The second that comes to mind is to populate the expected values when instantiating the object.
Person myPerson = new Person {Employed = true };
You can have multiple constructors with different inputs for a class:
public Person() {
this.Employed = false;
}
public Person(bool employed) {
this.Employed = employed;
}
public Person(bool employed,bool _isEmploye) {
if(_isEmploye)
this.Employed = true;
else
this.Employed = false;
}
and use appropriate inputs wherever you call:
Person p = new Person(true,true);
I am pretty new to OOP and looking into things in a bit more depth, but I have a bit of confusion between these 3 methods in C# and which one is best and what the differences are between 2 of them.
Example 1
So lets start with this one, which (so I understand) is the wrong way to do it:
public class MyClass
{
public string myAttribute;
}
and in this way I can set the attribute directly using:
myObject.myAttribute = "something";
Example 2
The next way I have seen and that seems to be recomended is this:
public class MyClass
{
public string myAttribute { get; set;}
}
With getters and setters, this where I dont understand the difference between the first 2 as the variable can still be set directly on the object?
Example 3
The third way, and the way that I understand the theory behind, is creating a set function
public class MyClass
{
string myAttribute;
public void setAttribute(string newSetting)
{
myAttribute = newSetting;
//obviously you can apply some logic in here to remove unwanted characters or validate etc.
}
}
So, what are the differences between the three? I assume example 1 is a big no-no so which is best out of 2 and 3, and why use one over the other?
Thanks
The second
public class MyClass
{
public string MyAttribute { get; set;}
}
is basically shorthand for:
public class MyClass
{
private string myPrivateAttribute;
public string MyAttribute
{
get {return myPrivateAttribute;}
set {myPrivateAttribute = value;}
}
}
That is an auto-implemented property, which is exactly the same as any regular property, you just do not have to implement it, when the compiler can do that for you.
So, what is a property? It's nothing more than a couple of methods, coupled with a name. I could do:
public class MyClass
{
private string myPrivateAttribute;
public string GetMyAttribute()
{
return myPrivateAttribute;
}
public void SetMyAttribute(string value)
{
myPrivateAttribute = value;
}
}
but then instead of writing
myClass.MyAttribute = "something";
string variable = myClass.MyAttribute;
I would have to use the more verbose, but not necessarily clearer form:
myClass.SetMyAttribute("something");
string variable = myClass.GetMyAttribute();
Note that nothing constraints the contents of the get and set methods (accessors in C# terminology), they are methods, just like any other. You can add as much or as little logic as you need inside them. I.e. it is useful to make a prototype with auto-implemented properties, and later to add any necessary logic (e.g. log property access, or add lazy initalization) with an explicit implementation.
What your asking here has to do with encapsulation in OOP languages.
The difference between them is in the way you can access the propriety of an object after you created an object from your class.
In the fist example you can access it directly new MyClass().MyAttribute whether you get or set it's value.
In the second example you declare 2 basic functions for accessing it:
public string MyAttribute
{
get {return myPrivateAttribute;}
set {myPrivateAttribute = value;}
}
In the third example you declare your own method for setting the value. This is useful if you want to customize the setter. For example you don't want to set the value passed, but the value multiplied by 2 or something else...
I recommend some reading. You can find something here and here.
Property is a syntactic sugar over private attribute with get and set methods and it's realy helpful and fast to type;
You may treat automatic property with { get; set;} as a public attribute. It has no additional logic but you may add it later without uset ever notice it.
Just exchange
public string MyLine { get; set;}
to
string myLine;
public string MyLine
{
get { return myLine; }
set { myLine = value + Environment.NewLine; }
}
for example if you need so.
You can also easily create read only property as { get; private set }.
So use Properties instead of public attributes every time just because its easier and faster to write and it's provides better encapsulation because user should not be used get and set methods if you decide to use it in new version of yours programm.
One of the main principles of OOP is encapsulation, and this is essentially the difference between the first example and the other 2.
The first example you have a private field which is exposed directly from the object - this is bad because you are allowing mutation of internal data from outside the object and therefore have no control over it.
The other 2 examples are syntactically equivalent, the second being recommended simply because it's less code to write. However, more importantly they both restrict access & control mutation of the internal data so give you complete control over how the data should be managed - this is ecapsulation.
My question stems from MVC's SelectList (and previous generations). Basically the class takes in an IEnumerable and uses the members you define as strings.
How does it interface with the object (casting, reflection?)
(probably redundant) How does it lookup the members as a string.
This is one facet of C# that I have been interested in but could never find examples of :(
EDIT:
I ended up using DataBinder.Eval() from System.Web.UI
It still has the overhead of reflection but makes things easier by allowing you to pass the object and a string containing the hierarchy of the member you want. Right now that doesn't really mean much, but this project was designed to take in Linq data, so not having to worry about it down the road makes my life a tad easier.
Thanks everyone for the help.
While I don't know about its implementation for sure, I'd expect it to use reflection.
Basically you call Type.GetProperty or Type.GetMethod to get the relevant member, then ask it for the value of that property for a specific instance (or call the method, etc). Alternatively there's Type.GetMembers, Type.GetMember etc.
If you want to be able to use "Person.Mother.Name" or similar "paths" you have to do that parsing yourself though, as far as I'm aware. (There may be bits of the framework to do it for you, but they're not in the reflection API.)
Here's a short but complete example:
using System;
using System.Reflection;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
class Test
{
static void Main()
{
Person jon = new Person { Name = "Jon", Age = 33 };
ShowProperty(jon, "Name");
ShowProperty(jon, "Age");
}
static void ShowProperty(object target, string propertyName)
{
// We don't need no stinkin' error handling or validity
// checking (but you do if you want production code)
PropertyInfo property = target.GetType().GetProperty(propertyName);
object value = property.GetValue(target, null);
Console.WriteLine(value);
}
}
Yes, via reflection. Take a look at the Type class and associated methods. A good place to start might be here.
You can always look at MVC's source for examples too.
My understanding is any method which does not modify state of the constaining class is a prime candidate to be made static because it does not touch the instance. An instance would be that containing class's data (fields/properties) so if I had a person class with a property called Name (and just that one property), and I am not modifying that property then my class can be set as static, but of course, but the function could be working with another object. Is this the right thing to look for when checking if a method should be made static?
Static variables are described as global variables, but what is the difference of this to any publicly variable? All the variables are in the server's memory and will be lost in a reboot etc. And then use this variable to hold expensive-to-get data (eg running stored procedures in a loop etc).
Thanks
My understanding is any method which does not modify state of the constaining class is a prime candidate to be made static because it does not touch the instance.
I wouldn't say it's a prime candidate, but rather just a candidate. Personally, I think methods should be made static if the API would suggest that it should be static from a logical, algorithmic standpoint. Technically, any method which doesn't change state can be static, but I don't believe it necessarily should be static.
and I am not modifying that property then my class can be set as static, but of course, but the function could be working with another object.
You can only set your class as static in C# if it has absolutely no instance variables. "Instances" of a static class don't exist (and cannot exist), nor can non-static members.
Now - for what I think you're really after...
The difference between a static variable and a non-static variable has to do with how it's accessed. When you define a static field on a class, you're defining a field that will always have a single instance (instance of the field) tied to the class itself. When you define a non-static, normal field, on the other hand, you will potentially have many instances of your field, each residing within one instance of your class.
This is why static variables are often described as global - anything that has access to the class has access to it's one copy of the static variable (provided its publicly accessible). However, non-static fields are different - you need to have a reference to the specific instance of the class in order to read or write to a non-static member.
.
My understanding is any method which
does not modify state of the
constaining [sic] class is a prime candidate
to be made static because it does not
touch the instance.
I don't think this is the right way to think of static vs. non-static. Rather, any method which is not related to the state of a class instance can be static. A name is obviously associated with a particular person, so a Name field on a Person class should almost certainly not be static. Otherwise, you could end up with a scenario like this:
public class Person {
public static string Name { get; set; }
public Person(string name) { Name = name; }
public override string ToString() {
return Name;
}
}
Person dan = new Person("Dan";
Person john = new Person("John";
// outputs "John"
Console.WriteLine(john);
// outputs "John" again, since Dan doesn't have a name property all his own
// (and neither does John, for that matter)
Console.WriteLine(dan);
EDIT: Now, suppose we have a property such as House which can belong to not one but several people. blade asks: "How would this be modeled in code - static?"
My answer: NO, for the same reason already mentioned above. Suppose I've fixed the problem above by making the Name property non-static. Then I introduce a new static House property. Now I have a situation like this:
public class Person {
public string Name { get; set; }
public static House House { get; set; }
public Person(string name, House house) {
Name = name;
House = house;
}
public override string ToString() {
return String.Concat(Name, ", ", House);
}
}
public class House {
public double SquareFootage { get; set; }
public House(double sqft) { SquareFootage = sqft; }
public override string ToString() {
return String.Format("House - {0} sq. ft.", SquareFootage);
}
}
House danAndKatsHouse = new House(1000.0);
House johnsHouse = new House(2000.0);
Person dan = new Person("Dan", danAndKatsHouse);
// outputs "Dan, House - 1000 sq. ft." as expected
Console.WriteLine(dan);
Person kat = new Person("Kat", danAndKatsHouse);
// outputs "Kat, House - 1000 sq. ft.", again as expected
Console.WriteLine(kat);
Person john = new Person("John", johnsHouse);
// outputs "John, House - 2000 sq. ft.", so far so good...
Console.WriteLine(john);
// but what's this? suddenly dan and kat's house has changed?
// outputs "Dan, House - 2000 sq. ft."
Console.WriteLine(dan);
There's a difference between multiple objects of one class sharing the same object and ALL objects of that class sharing the same object. In the latter case, a static property makes sense; otherwise, it does not.
There are a few ways off the top of my head to deal with this scenario. They are:
1. Make the House property non-static
It might seem strange, but you can always just make the House property non-static and you won't ever have to worry about the problem above. Furthermore, assuming you actually do assign the same House object to each Person who shares it, making a change to the House through one Person object will actually achieve the desired effect:
House danAndKatsHouse = new House(1000.0);
// (after making Person.House property non-static)
Person dan = new Person("Dan", danAndKatsHouse);
Person kat = new Person("Kat", danAndKatsHouse);
dan.House.SquareFootage = 1500.0;
// outputs "1500"
Console.WriteLine(kat.House.SquareFootage);
This could actually be a problem, however, if you accidentally assign the same House to two people with the intention of them actually having two different Houses:
House smallerHouse = new House(1000.0);
House biggerHouse = new House(2000.0);
Person dan = new Person("Dan", smallerHouse);
Person john = new Person("John", biggerHouse);
Person bill = new Person("Bill", smallerHouse);
bill.House.SquareFootage = 1250.0;
// yikes, Dan's house just changed...
Console.WriteLine(dan);
2. Use a database
The fact is that the notion of making a house a property of a person is somewhat a forced concept to begin with. A person may move out of their house, different people may move in, etc. Really a relationship exists between the two, which makes using a database an appropriate solution.
Using this approach, what you'd do is have a Persons table, a Houses table, and a third table (maybe PersonHouses) containing id pairs from the other two tables to represent, I guess, home ownership.
If you don't have a full-blown database at your disposal, you can achieve effectively the same result (in .NET) using a System.Data.DataSet and its collection of System.Data.DataTable objects in your code. However, in any scenario where you are translating rows of a database (or DataTable) to objects and then back again, you do need to be aware of impedence mismatch. Basically, whatever meticulous precautions you take in your code to encapsulate your data are out the window once that data is in the database, ready to be modified by anyone with sufficient permissions.
3. Use dictionaries
Another approach, similar to using a database but a bit more work (and I think some programmers who've gone the DataSet route shudder at the thought of this), is to use dictionaries to keep track of your Person and House objects. The quickest way to implement this approach would be to have a Dictionary<int, Person> and a Dictionary<int, House>, and assign each Person a HouseId property:
public class Person {
public int Id { get; private set; }
public string Name { get; set; }
public int HouseId { get; set; }
private static int LastIdValue { get; set; }
private static Dictionary<int, Person> People { get; set; }
static Person() {
LastIdValue = 0;
People = new Dictionary<int, Person>();
}
// make the constructor private to disallow direct instantiation
private Person(int id, string name, int houseId) {
Id = id;
Name = name;
HouseId = houseId;
}
// only permit construction through this function, which inserts
// the new Person into the static dictionary before returning it
static public Person NewPerson(string name, int houseId) {
Person p = new Person(LastIdValue++, name, houseId);
People.Add(p.Id, p);
return p;
}
static public Person getPersonById(int id) {
Person p = null;
return People.TryGetValue(id, out p) ? p : null;
}
}
public class House {
public int Id { get; private set; }
public int SquareFootage { get; set; }
private static int LastIdValue { get; set; }
private static Dictionary<int, House> Houses { get; set; }
static House() {
LastIdValue = 0;
Houses = new Dictionary<int, House>();
}
// make the constructor private to disallow direct instantiation
private House(int id, int sqft) {
Id = id;
SquareFootage = sqft;
}
// only permit construction through this function, which inserts
// the new House into the static dictionary before returning it
static public House NewHouse(int sqft) {
House h = new House(LastIdValue++, sqft);
Houses.Add(h.Id, h);
return h;
}
static public House getHouseById(int id) {
House h = null;
return Houses.TryGetValue(id, out h) ? h : null;
}
}
House firstHouse = House.NewHouse(1000.0);
House secondHouse = House.NewHouse(2000.0);
Person dan = Person.NewPerson("Dan", firstHouse.Id);
Person kat = Person.NewPerson("Kat", firstHouse.Id);
Person john = Person.NewPerson("John", secondHouse.Id);
House dansHouse = House.getHouseById(dan.HouseId);
House katsHouse = House.getHouseById(kat.HouseId);
// this prints
if (katsHouse == dansHouse) { Console.WriteLine("Dan and Kat live in the same house."); }
// this also prints
if (dansHouse == firstHouse) { Console.WriteLine("Dan and Kat live in the first house."); }
// this does not print
if (dansHouse == secondHouse) { Console.WriteLine("Dan and Kat live in the second house."); }
This way, all your data encapsulation still holds. However, if you ever need your data to persist between instances of your code running, then you need to serialize your dictionaries in some file format (most likely XML), which could then be edited by anyone with sufficient privileges, and then you're back to the impedence mismatch problem of using a database all over again.
In light of the advantages and disadvantages of each approach, I think what actually makes the most sense -- and makes your life easiest -- is to simply make House a non-static property. This is assuming you don't have tons and tons of Person and House objects to keep track of.
" if I had a person class with a
property called Name (and just that
one property), and I am not modifying
that property then my class can be set
as static"
That is not correct. A person class is almost certainly a domain entity. It is conceivable you might want to have a static method on a Person entity, but I haven't ever come across one. In your example, you would have a private setter for your 'Name' property.
The static-ness of anything should model your domain, rather than being a language implementaion detail.
There are no true globl variables in C#, in the sense that that term is used in other languages like C. The difference between a static object and a global object is that a static object has permissions that are relative to the class in which it is defined. This is a very good thing, because you can create private static members that are only accessible to member of one class. The big problem with the abuse of global variables is the many depenencies to a single global variable that can evolve across a large colleciton of modules. Private static object avoid this problem.
One big problem with static objects is that they are not thread safe. In order to declare a thread safe static object, you must use the ThreadStatic attribute and provide a way for the object to be initialized on first access. You should do this for all multi-threaded environents e.g. ASP.NET, and any general purpose library that might run in multi-threaded environment. Heck, just always do this and you won't be sorry!
If you have a Person class with a static field name:
public class Person {
public static string Name { get; set; }
}
then you can only ever have one name. You can not have a list of persons with different names. Static can be seen as "Unique" in the way that it's value is global. This can be a trap in ASP.net applications by the way, because static applies through the entire application, which means to all users.
Static variables are rather rare and used for data that is really not part of a specific instance of the class. Or to return specific instances.
For example, Guid.Empty is a static field that returns a Guid that has all Bits set to 0.
A good example is System.Drawing.Color. Color has instance-specific variables, for example R,G,B and Alpha, but you have static fields like Color.Black which returns a Black color.
I have a Person object with two constructors - one takes an int (personId), the other a string (logonName). I would like another constructor that takes a string (badgeNumber). I know this can't be done, but seems it might be a common situation. Is there a graceful way of handling this? I suppose this would apply to any overloaded method. Code:
public class Person
{
public Person() {}
public Person(int personId)
{
this.Load(personId);
}
public Person(string logonName)
{
this.Load(logonName);
}
public Person(string badgeNumber)
{
//load logic here...
}
...etc.
You could perhaps use factory methods instead?
public static Person fromId(int id) {
Person p = new Person();
p.Load(id);
return p;
}
public static Person fromLogonName(string logonName) {
Person p = new Person();
p.Load(logonName);
return p;
}
public static Person fromBadgeNumber(string badgeNumber) {
Person p = new Person();
// load logic
return p;
}
private Person() {}
You might consider using custom types.
For example, create LogonName and BadgeNumber classes.
Then your function declarations look like...
public Person(LogonName ln)
{
this.Load(ln.ToString());
}
public Person(BadgeNumber bn)
{
//load logic here...
}
Such a solution might give you a good place to keep the business logic that governs the format and usage of these strings.
You have four options that I can think of, three of which have already been named by others:
Go the factory route, as suggested by several others here. One disadvantage to this is that you can't have consistent naming via overloading (or else you'd have the same problem), so it's superficially less clean. Another, larger, disadvantage is that it precludes the possibility of allocating directly on the stack. Everything will be allocated on the heap if you take this approach.
Custom object wrappers. This is a good approach, and the one I would recommend if you are starting from scratch. If you have a lot of code using, e.g., badges as strings, then rewriting code may make this a non-viable option.
Add an enumeration to the method, specifying how to treat the string. This works, but requires that you rewrite all the existing calls to include the new enumeration (though you can provide a default if desired to avoid some of this).
Add a dummy parameter that is unused to distinguish between the two overloads. e.g. Tack a bool onto the method. This approach is taken by the standard library in a few places, e.g. std::nothrow is a dummy parameter for operator new. The disadvantages of this approach are that it's ugly and that it doesn't scale.
If you already have a large base of existing code, I'd recommend either adding the enumeration (possibly with a default value) or adding the dummy parameter. Neither is beautiful, but both are fairly simple to retrofit.
If you are starting from scratch, or only have a small amount of code, I'd recommend the custom object wrappers.
The factory methods would be an option if you have code which heavily uses the raw badge/logonName strings, but doesn't heavily use the Person class.
No.
You might consider a flag field (enum for readability) and then have the constructor use htat to determine what you meant.
That won't work. You might consider making a class called BadgeNumber that wraps a string in order to avoid this ambiguity.
You cannot have two different constructors/methods with the same signature, otherwise, how can the compiler determine which method to run.
As Zack said, I would consider creating an "options" class where you could actually pass the parameters contained in a custom type. This means you can pretty much pass as many parameters as you like, and do what you like with the options, just be careful you dont create a monolithic method that tries to do everything..
Either that, or vote for the factory pattern..
You could use a static factory method:
public static Person fromLogon(String logon) { return new Person(logon, null); }
public static Person fromBadge(String badge) { return new Person(null, badge); }
As has been suggested, custom types is the way to go in this case.
If you are using C# 3.0, you can use Object Initializers:
public Person()
{
}
public string Logon { get; set; }
public string Badge { get; set; }
You would call the constructor like this:
var p1 = new Person { Logon = "Steve" };
var p2 = new Person { Badge = "123" };
Only thing I can think of to handle what you're wanting to do is to have to params, one that describes the param type (an enum with LogonName, BadgeNumer, etc) and the second is the param value.
You could switch to a factory style pattern.
public class Person {
private Person() {}
public static PersonFromID(int personId)
{
Person p = new Person().
person.Load(personID);
return p;
this.Load(personId);
}
public static PersonFromID(string name)
{
Person p = new Person().
person.LoadFromName(name);
return p;
}
...
}
Or, as suggested, use custom types. You can also hack something using generics, but I wouldn't recommend it for readability.
Depending on your business constraints:
public class Person
{
public string Logon { get; set; } = "";
public string Badge { get; set; } = "";
public Person(string logon="", string badge="") {}
}
// Use as follow
Person p1 = new Person(logon:"MylogonName");
Person p2 = new Person(badge:"MyBadge");
How about ...
public Person(int personId)
{
this.Load(personId);
}
public Person(string logonName)
{
this.Load(logonName);
}
public Person(Object badgeNumber)
{
//load logic here...
}