Say I have this simple class
public class MyEntity
{
public DateTime DateUpdated { get; private set; }
public string Author { get; private set; }
public string Comment { get; private set; }
public void AddComment(string comment, string author)
{
Author = author;
Comment = comment;
DateUpdated = DateTime.Now;
}
}
I have made the setters private to encapsulate the class and added the AddComment method to add some behaviour to my class. This works perfectly fine when creating a new object but when I want to load the Entity from the db the DateUpdated is of course set to the current date which I would like to avoid.
Is there any patterns I could use to avoid making the DateUpdated setter public as that does seem to break my nice encapsulation and messing up the clean interface of the class? The class is of course just an example of a more generic problem.
The closest I have got to now without making more public constructors is creating a private constructor which I access through a public static method.
Use a constructor that takes parameters matching the fields of the object.
This will allow you to populate the objects on startup and keep them immutable.
public MyEntity(DateTime dateUpdated, string author, string comment)
{
DateUpdated = dateUpdated;
Author = author;
Comment = comment;
}
Look into the Memento pattern for re-hydrating your object. Use the constructor only for creating a new instance.
You can overload the AddComment method like so:
public class MyEntity
{
public DateTime DateUpdated { get; private set; }
public string Author { get; private set; }
public string Comment { get; private set; }
public void AddComment(string comment, string author)
{
Author = author;
Comment = comment;
DateUpdated = DateTime.Now;
}
public void AddComment(string comment, string author, DateTime dateUpdated)
{
Author = author;
Comment = comment;
DateUpdated = dateUpdated;
}
}
If you are using an ORM such as NHibernate to implement the repository, then it will assign values to properties based on data from the database even if the properties are private set. In other words, it bypasses the AddComment method and injects data directly. This makes sense because when reconstituting an entity, behavior doesn't repeat, only the data needs to be copied. NHibernate does require the entity to contain a protected parameter-less constructor. If using your own ORM implementation, then you can employ the constructor pattern as suggested by Oded because in that case your entity can truly remain persistence ignorant.
If the repository responsible for creating these objects lives in the same assembly, you should check out the internal access modifier. If this fits your project's needs, you can implement it in one of two ways...
Change your setters from private to internal. The creator would then just set the values of the properties after instantiation.
Add an internal constructor that accepts a value for all the properties and sets them up.
Either way, you can still allow change through public methods as you demonstrated in your example.
Related
I am a bit confused so to why we set the set as private in the following. My confusion is not specifically to do with the private property, but in the context of domain objects and getting them from the user input ([FromForm])
public class ObjectA
{
public string Name { get; private set; }
public string Title { get; private set; }
public ObjectA(string name, string title)
{
Name = name;
Title = title;
}
}
But in reality when ObjectA is passed into a controller with [FromBody], all those properties get sent into the constructor automatically defeating the purpose of private set.
I guess I am not fully understanding this whole concept of private sets in domain objects
It's common rule when design DDD objects. makes object to be immutable. Property's value should be changed only inside your domain via constructor or public method. That helps you more focus to your domain and avoid side effects.
Kind of these objects are not the Data Transfer Object(DTO) that you mentioned: [FromBody]
I have code as below
public class LocalDB
{
public static int e_SessionID;
public static string e_EventName;
public static string e_TimeCreate;
}
in other class:
public static LocalDB newEvent ;
public void something()
{
newEvent.e_SessionID=123;
}
but it is can not pass value.
Problem : You are trying to access the static feilds using instance reference variable newEvent as below:
newEvent.e_SessionID=123;
//^^^Here
Solution : You need to use classname to access the static fields
newEvent.e_SessionID=123;
//^^^Replace with classname LocalDB here
Replace this:
newEvent.e_SessionID = 123;
With this:
LocalDB.e_SessionID = 123;
Why don't you set them up as properties? Have a read of this SO post why prefer properties to public variables
"Fields are considered implementation details of classes and exposing them publicly breaks encapsulation."
public class LocalDB
{
public int SessionID { get; set; }
}
Static methods and variables can only invoke using the class name
and you are trying to call using the class object.
if you want to set the value of e_SessionID set the value using class name as follows
LocalDB.e_SessionID=123;
try to use property instead:
public class LocalDB
{
public int e_SessionID { get; set; }
public string e_EventName { get; set; }
public string e_TimeCreate { get; set; }
}
Prefer instance data to static data.
Static data is effectively global state. Do you have only one event in the lifetime of your program? What if you need to support multithreading? This is object-oriented programming; use objects.
Encapsulate data.
Avoid making fields public. Prefer properties, as others have stated. Note that this allows assigning the creation time at construction (and only then).
Use appropriate types.
If you are storing a date/time value, normally you would use the DateTime class.
Favor immutability.
If you know the values of properties at construction time, set them then and don't allow them to be changed.
Think about names.
Descriptive names matter, especially when you're doing maintenance after six months. I didn't change the name of LocalDB in my example, as I don't know your domain or use case. However, this class looks more like an event than a database to me. Would Event be a better name?
The following example uses C# 6 syntax; earlier versions would need to add private setters and move the initialization to the constructor.
public class LocalDB
{
public LocalDB(int sessionID, string eventName)
{
SessionID = sessionID;
EventName = eventName;
}
public int SessionID { get; }
public string EventName { get; }
public DateTime TimeCreate { get; } = DateTime.UtcNow;
}
public class Other
{
public void DoSomething()
{
NewEvent = new LocalDB(1, "Other Event");
}
public LocalDB NewEvent { get; private set; }
}
A flaw in this example is that the NewEvent property of an Other instance will be null on creation. Avoid nulls where possible. Perhaps this should be a collection of events; not knowing your use case I can't say.
I want to call non-static variable from another class. If I make it static, it affects my other code.
I've two classes Harvest_Client and Harvest_Project.
In my Harvest_Project class I've
public int _client_id{ get; set;}
I'just want to do in Harvest_Client class is,
public int _id = Harvest_Project._client_id;
How should I do this?
Firstly, you should rename the property (it's not a variable) to conform with .NET naming conventions, e.g.
public int ClientId { get; set; }
Next, you need an instance of HarvestProject (post-renaming). Don't just create a new one - you need the right instance, the one whose client ID you're interested in. We can't tell you which one it is - but if you don't already have an instance of HarvestProject to hand, you should work out how you're expecting to specify which client ID you want.
Think of it this way: if I were to ask you "How old is a person?" you'd naturally want to know which person I was talking about. It's exactly the same here.
maybe passing the reference to the class will do what you need:
public class Harvest_Project
{
public string Name { get; set; }
public int clientId { get; set; }
}
public class Harvest_Client
{
private Harvest_Project MyInstance;
private int myid;
public int MyId
{
get
{
return myid;
}
private set
{
MyId = value;
}
}
public Harvest_Client(Harvest_Project cls)
{
MyInstance = cls;
MyId = cls.clientId;//since class reference present no
//need for the property.
//its just here to show if in your
//project you really just need ID
//in this example its redundant
}
}
Depending on what you are trying to do you can make a List of Harvest_Project objects or better a dictionary,if there are various types of "projects" they could be all placed in a dictionary cataloged accordingly to the specified key.
One moment I would like to recommend to take into consideration the following declaration of property public int ClientId {get; private set;"} It allow you to prohibited setting this variable from third party code, if you actually need this. Otherwise you will have ordinary global variable
If I want to set my property in a Class private, so it should be only possible to use and set this property in this class, what is the better way? This
public string Name { private get; private set }
or
private string Name { get; set }
hmmm and there is also
private string Name { private get; private set }
It's worth noting that originally, C# wouldn't let you set different accesses on a getter or setter, so the only possible choices were:
public string Name { get; set; }
protected internal string Name { get; set; }
internal string Name { get; set; }
protected string Name { get; set; }
private string Name { get; set; }
(For that matter, you couldn't have automatic properties and always had to do the writing to and from a backing field yourself, but we'll ignore that just because we'll have shorter examples that way).
It is often useful to have different accesses for the two, most often a more restrictive setter than getter, and so the likes of
public string Name { get; private set; }
was introduced.
Now, by extension of that, it would seem logical enough to allow:
public string Name { private get; private set; }
private string Name { private get; private set; }
However, what are these two expressing?
The second isn't too bad, it's just needlessly repetitious. Still though, it's quite likely that some confused thinking got us there (most likely an incomplete refactoring). Good code is as much about expressing what you are doing as making a computer do something (if anything, more so), better to have it express clearly.
Hence if you end up with the likes of { private get; private set; } then it'd likely be worth looking at again and thinking about what you really want to say here. Hurrah for it being a compiler error.
The first case is even worse. It says "this property is public, except for the setter that is private, and the getter that is private". That's not an exception, "it's this thing, except for all the time" is no real expression of anything. Doubly hurrah the compiler for not letting us do it.
Have you tried compiling your examples? Only the middle one will translate.
If you want to specify extra accessibility level keyword, you can only do it on one of the accessors (getter/setter), and that level of the accessor must be more restrictive than the accessibility of the entire property.
Here you see the rules: Restricting Accessor Accessibility
public string Name { get; private set; }
This is what I think you are wanting to do.
There is no point trying to make the get private when the property is public unless you only want your class to see it. In that situation you should use:
private string Name { get; set; }
Update: On second read, you definitely want the second example.
The better way depends on what you want:
public string Name { private get; private set } The property is public but noone can read or wrote to it, except class itself. That is completely useless, so use just
private string Name { get; set }.
In general if you view the property like a couple of methods (which actually is)
private string get_Name() { }
private string set_Name(value) { }
The reason of having a possibility to apply that identifiers to a property get/set becomes evident, I hope.
For a private member, you don't need to define accessors.
Just do this:
private string _name;
It seems like you want
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
this would allow you to access private string Name.
surely enough,
That is the definition of private classifier in OOP: just allow access within methods and scope of the class that owns such private member. Thus if your aim is to disable anyother means of access to a particular member of a class, claiming it as:
private <Type_name> <member_identifier> ;
is the simplest and enough to make it such.
I have a web service that will return a List where Person is a DTO. Is there any reason I shouldn't define Person like:
public class Person {
public string Name;
public string Email;
}
instead of
public class Person {
private string _name;
public string Name {
get {
return _name;
}
set {
_name = value;
}
}
}
The second version is more verbose, and I can't see any reason public instance variables could be a problem here. Any reason it could be?
Properties are preferred over fields to support
binding; fields cannot be bound
polymorphism; you can't do public virtual string Name;
You can use automatic properties to reduce the verbosity
public class Person {
public string Name { get; set; }
public string Email { get; set; }
}
In general - this is a design decision - see: http://forums.asp.net/t/1233827.aspx
But the DTO implementation is slightly different. Since this is just a DTO and there is no behavior with no set/get property specific implementation the usage you could just as well use the less verbose method. Any implementation change would not require client recompiles since they will be serialized the same way in either case via a service, so your smaller implementation is fine.
Fyi though - if the client is going to use these classes for databinding then they need to be properties in the class. Fields won't be bound.
In addition to all of the other answers, properties allow for validation to be ran when the property is read from or written to. That would take more work to do when using fields.