I'm making classes and I wanted to know the differnce in the application of the getters and setters.
e.g.
public class Employee
{
private string forename;
public string Forename { get { return forename; } }
private string surname;
public string Surname { get { return surname; } }
private int age;
}
In what I have made I have 'private string forename;'. Because it doesn't have {get;set;} is it a variable instead of a field in the class? Also because it is private I have used a property with the same name in order to access forename.
I guess my question is what is the point in having the separate Forename/forename if I have to write {get; set;} for the private one as well as the public one. Is there a better way to write the fields? Couldn't I just have written:
private string forename{ get { return forename; } }
e.g. for my password field I have:
private string password;
public string Password
{ set
{
bool validPassword = false;
if (value.Length > 7 & value.Length < 15)
{
if (value.Any(char.IsLower))
{
if (!value.Contains(" "))
{
if (value.Any(char.IsUpper))
{
string specialChar = #"%!##$%^&*()?/>.<,:;'\|}]{[_~`+=-" + "\"";
char[] specialCharArray = specialChar.ToCharArray();
foreach (char ch in specialCharArray)
{
if (value.Contains(ch))
{
validPassword = true;
Console.WriteLine("Password has been changed");
break;
}
}
}
}
}
}
Couldn't I have just put this all in a {set} on the private password?
password is a private field, and Password is a public property.
You are correct that you could put this logic directly in the set block of the private password field.
But by using a property with a set block instead of a field with a set block, you can specify the logic for validating and assigning the password value at a single place, and you can expose the password value to other codes through the property. It makes your code easier to maintain and understand.
user can simply assign a password like this employee.Password = "#$##%##%##!"; without knowing the internal details. you can also change this implementation in future without breaking anything.
In short properties are the wrapper around fields.
Forename property only has a getter, which means that it is a read-only property.
Here is the official documentation of properties, you can refer this as well.
Related
I have a property that has a Setter with a logic inside it (to generate random string for an Id).
public class Customer
{
private string _customerId;
public string CustomerId
{
get { return _customerId; }
private set { _customerId = Utilities.RandomString(6); }
}
public string CustomerName { get; set; }
}
But how can I call this property from another class, to actually trigger the logic inside the Setter?
class Program
{
static void Main(string[] arg)
{
var customer = new Customer();
customer.CustomerName = "John";
customer.CustomerId = ?????
}
}
Or am I over-complicating things and should not use this logic inside this property?
You should remove private modifier from the setter to be able to set values for that property from the outside of the Customer class.
But, looking at your code, it seems that you don't need that logic in setter. Instead you could assign random customer ID in the constructor.
As #Alexander Goldabin said, the constructor would be a better place for this logic, if the goal is that the customer ID is always randomly generated. There are situations where it makes sense to have logic in a setter, but generating an initial value is better suited for a constructor.
Additionally, I would keep the setter private if the calling code should not be able to update the randomly-generated value:
public class Customer
{
public Customer()
{
CustomerId = Utilities.RandomString(6);
}
public string CustomerId { get; }
public string CustomerName { get; set; }
}
(Note that the constructor is allowed to modify the getter-only property, but nothing else can.)
Your property setter is declared as private, so you won't be able to assign to it from another class. Remove the private accessor from the property, then you could assign any value you wish to really, since you're not using value inside the setter. So like the following:
customer.CustomerId = "any-string-here";
That being said, I don't believe this is the best way to achieve the required outcome. A potential alternative method, is to generate the random ID when the value of the property is retrieved for the first time. You can then do away with the setter entirely. A proposed solution:
public class Customer
{
private string _customerId;
public string CustomerId
{
get
{
if (string.IsNullOrWhiteSpace(_customerId))
_customerId = Utilities.RandomString(6);
return _customerId;
}
}
public string CustomerName { get; set; }
}
building using Webforms
I have a number of classes they contain all sorts of properties:
Lets say:
USER:
Forename,
Surname,
EyeColour,
FavouriteIceCream
In different parts of my site I need to display a list of users thus:
Bob Jones,
Fred Smith,
Susan Gifford
whereas in other parts I need a list:
GIFFORD, Susan
JONES, Bob
SMITH, Fred
Like wise I might need to abbreviate their names to
BJo
FSm
SGi
In my head it seems sensible to have additional properties inside my class called:
Fullname (forename + ' ' + surname)
Reverse (ToUpper(surname) +', ' + forename)
Intials
which are filled at time of creating the USER object and so later when I want to display Bob I can call
ThisUser.FullName rather than
ThisUser.Forename + " " + ThisUser.Surname
Is it bad practice to be creating extra properties at time of creation if I'm not going to be using them often?
Obviously I've simplified here but is it bad to have the FavouriteIceCream field being substantiated every time I refer to a User even if I only use their favourite flavour on a page viewed infrequently.
To me it seems a good way to be consistent, any page that wants to use the reverse format of a name is always going to be JONES, Bob rather than sometimes Jones, Bob if the page is written by one of the team who has forgotten the format required
The other side of the argument I guess would that we have a bare minimum user class and we pull in the extra fields only when we need to know their dairy preferences
//additional,
if it makes a difference, internal intranet based webform so only 200 users
Is it bad practice to be creating extra properties at time of creation if I'm not going to be using them often?
Yes. Use read-only calculated properties:
public String Fullname {
get {
return Forename + " " + LastName;
}
}
I think that storing these properties’ values at the time the instance is created is a bad idea. But you still can use properties getters like this:
string Forename;
string Surname;
// set value for the private properties as usual
public User(string fn, string sn)
{
Forename = fn;
Surname = sn;
}
// getters
public string DefaultName
{
get { return Forname + “ “ + Surname; }
}
public string ReversedName
{
get { return Surname + “ “ + Forename; }
}
without taking extra space in memory for data that you just can manipulate at runtime. Otherwise, you can created methods for getting manipulated name, as the other answer suggested. Anyways, never storing redundant data is always best
which are filled at time of creating the USER object [...] have the field being substantiated every time I refer to a User...
Are you talking about creating static properties that you would populate? Why not just create dynamic properties? Something like this:
public string Fullname { get { return $"{Forename} {Surname}"; } }
public string Reverse { get { return $"{Surname.ToUpper()}, {Forename}"; } }
// etc.
There's no need to populate the same data twice, and these won't be used until you call them.
Basically it's not a choice between duplicating data vs. putting the logic all over the application, it's a choice between putting the logic all over the application or putting it on the object. Just put the logic on the object.
As usual: it depends.
Filling a bunch of properties of a class to hold various versions of the same informations is IMHO not the best idea.
Depending on how complex this creating is and on how many places it will be used, this could be either just an extension method, a private method within the view that needs that specific kind of view or a direct property of the class itself.
By using a property of the class itself you have at least four possibilities:
Fill up while creating the object (if it is immutable)
public class Person
{
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
FullName = $"{FirstName} {LastName}";
}
public string FirstName { get; }
public string LastName { get; }
public string FullName { get; }
}
Fill it up when the depending setter was called (if it is mutable)
public class Person
{
private string _firstName;
private string _lastName;
public string FirstName
{
get => _firstName;
set
{
_firstName = value;
UpdateFullName();
}
}
public string LastName
{
get => _lastName;
set
{
_lastName = value;
UpdateFullName();
}
}
public string FullName { get; private set; }
private void UpdateFullName()
{
FullName = $"{FirstName} {LastName}";
}
}
Create the value on the fly whenever it will be called (multiple times if called multiple times)
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName => $"{FirstName} {LastName}";
}
Create the value once when it is called and return this result until the depending value has been changed.
public class Person
{
private string _firstName;
private string _lastName;
private Lazy<string> _fullName;
public string FirstName
{
get => _firstName;
set
{
_firstName = value;
UpdateFullName();
}
}
public string LastName
{
get => _lastName;
set
{
_lastName = value;
UpdateFullName();
}
}
public string FullName => _fullName.Value;
private void UpdateFullName()
{
_fullName = new Lazy<string>(()=> $"{FirstName} {LastName}");
}
}
Especially the usage of Lazy<> can help in the case of complex creation that is only used in certain places. It will compute the value once on the first call and then return the computed result on all consecutive calls. If the value should be re-evaluated (on the next call to it) you simply instantiate a new version of the Lazy<> instance.
If you would combine the Lazy<> approach with immutability you could also get something like this (which would be my pick, if the constraints allow it):
public class Person
{
private Lazy<string> _fullname;
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
_fullname = new Lazy<string>($"{FirstName} {LastName}");
}
public string FirstName { get; }
public string LastName { get; }
public string FullName => _fullname.Value;
}
Following on from my earlier question: c-sharp-convert-existing-class-to-use-properties-correctly
I have a class like this:
public class TestCaseInfo
{
public string text { get; set; } = "";
public string requirement_ref { get; set; } = "";
public string given { get; set; } = "";
public string when { get; set; } = "";
public string then { get; set; } = "";
public UInt32 timeLimit { get; set; } = 0;
}
I was previously populating the structure like this:
if (!getNodeValue(testcase_node.SelectSingleNode("text"), ref testcaseInfo.text))
errStr += nodeError(testcase_node, "Missing 'text' node");
Note: that I am trying to pass it by reference. I have read a load of quetions that all basically say that you can't do this. Fair enough...
So I want to pass in the "real" value (I think its called the backing value?) instead. Something like:
if (!getNodeValue(testcase_node.SelectSingleNode("text"), ref testcaseInfo._text)) // where '_text' should be the 'backing' value.
errStr += nodeError(testcase_node, "Missing 'text' node");
But I am missing two things (probably more!):
What is the backing value called?
I assume its private? - can I make it protected and make it a friend class? (that might be C++ talk... not sure if there is the same idea in C#)?
There is no valid identifier for the backing field for that property. You could not use an auto property, and instead explicitly define the get and set methods of the property, along with your own backing field, thus giving you a valid identifier for the backing field, although it would be very poor design to expose this backing field externally.
What you should do is re-design your code such that you don't need to pass the value by reference in the first place. You should just be passing the string by value and, if the result of this function is the computation of a string, returning it. The caller can then set that string back to the property if that's what they want. That would be the more idiomatic design. (Since you also have a boolean value you'd need to pass both the string and the boolean out, of course.)
As far as you are concerned, your properties may as well not have backing fields. The backing field isn't called anything you can refer to if you didn't explicitly declare it:
private string _name;
public String Name { get { return _name; } set { _name = value; } }
If you write properties with explicit backing fields, as above, you can pass them by ref into a method.
private int _id;
public String ID { get { return int _id; } set { int _id = value; } }
public void Test()
{
Int32.TryParse("Sausage Factory", out _id);
}
Let's say I have a class of some object representing a Page which has two properties strTitle where the original title is stored and strUrlTitlewhere I want to store the URL friendlz title.
I want to assign the strUrlTitleonly when assigning the strTitle therefore I have used the following code.
public class Page
{
public strUrlTitle {get; private set;}
public strTitle {
get
{
return strTitle;
}
set
{
strTitle = value;
strUrlTitle = HttpUtility.UrlEncode(value.Replace(" ", "-").Trim());
}
}
}
But It appears as if when the set method i called and it assigns the strTitle value, the set method is called again and we end up in infinite loop. Hence my question is how to assign both values from one get method?
Thanks
You need to create a backing field. Now your setter and getter call themselves, causing an infinite loop:
private string _title;
public Title
{
get
{
return _title;
}
set
{
_title = value;
UrlTitle = HttpUtility.UrlEncode(value.Replace(" ", "-").Trim());
}
}
public UrlTitle { get; private set; }
See also I am getting into infinite loop in property setter and probably many other potential duplicates if you search for "C# property setter infinite loop".
This question already has answers here:
Public Fields versus Automatic Properties
(14 answers)
Closed 10 years ago.
I am creating a simple User class, does it matter if I use public properties with private fields verses just using public fields?
Here is an example of what I mean:
public class clsUser
{
private string name;
private string lName;
public string Name
{
get
{
return name;
}
set
{
name= value;
}
}
public string LName
{
get
{
return lName;
}
set
{
lName= value;
}
}
public clsUser(string userID)
{
//get the user id here and set the properties
this.name= getName(userID);
this.lName= getLName(userID);
}
}
or can I just make
public string name;
public string lName;
public and now worry about typing out all of these:
public string Name
{
get
{
return name;
}
set
{
name= value;
}
}
I am then going to populate a form using these on another page like so:
clsUser cUser - new clsUser("myid");
txtSomething.Text = cUser.name;
and so on...
I guess my question is why do I need to retype the properties first as private and then as public (as I've seen in all web examples). Why not just make them public to begin with?
You're confusing fields with properties.
String name; is a field.
Unlike a property, you have no control over it.
If you eventually decide to add validation or change events or other logic, you'll need to change it to a property, which will break compiled code.
Certain features (eg, bindings) also can only work with properties.
Instead, you can use auto-implemented properties to make the compiler generate all of that boilerplate:
public String Name { get; set; }