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;
}
Related
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.
When I create this class and open a List with this custom class, the one with FullName can be seen in the inspector, but the one with Age cant be. I wonder why? Since the Age is public property, it should be seen as it is public get and set.
[Serializable]
public class YoungPerson
{
public string FullName;
public string fullname
{
get { return FullName;}
set { FullName = value; }
}
public int Age { get; set; }
public YoungPerson(string fullName, int age)
{
this.FullName = fullName;
this.Age = age;
}
}
Result
Because what you see in the Inspector is not the property
public string fullname { ... }
but rather the serialized field
public string FullName;
You can already see that on the naming - fullname would be displayed as Fullname not as Full Name as per ObjectNames.NicifyVariableName ;)
Unity's Serializer doesn't serialize properties by default - see Script Serialization -> Serialization of properties.
You can either add a backing field implementation like you also did for the name e.g.
// In that case I would always rather go for private
// anything else is just confusing / why would you use the property
// when you can anyway read/write the field directly
[SerializeField] private int age;
public int Age
{
get => age;
set => age = value;
}
or - as already mentioned by this answer - force serialize the property via (unfortunately undocumented for whatever reason)
[field: SerializeField]
public int Age { get; set; }
as also mentioned by the other answer this has some hickups (see e.g. this thread) though
Unity Editor dont show property in Inspector, you see on public string FullName field but not public string fullName property. Make public field for Age to see this in inspector
Unity can't serialize properties, it's mentioned in the docs.
As others have mentioned, Unity does not officially support serializing properties.
But it is possible.
This should work just fine:
[field: SerializeField] public string FullName { get; set; }
However, it still has some quirks, as mentioned here. You'll have to judge for yourself whether it's a good idea to use it.
If I had a method like below:
public Person GetPerson(int id)
{
// code that returns a Person where id is == id
}
Let's also so that Person looks like this:
public class Person
{
public int id {get; set;}
public string firstName {get; set;}
public string lastName {get;set}
}
I know that I could call it like so:
string name = GetPerson(someId).firstName;
What is the syntax where I could chain the firstName and lastName together? I am aware that some of the answers might be, "just create a field fullName" but I am actually just trying to expand my knowledge of C# to see if there is a way to chain those fields together WITHOUT doing this:
string name = $"{GetPerson(someId).firstName} {GetPerson(someId).lastName}";
Also, I don't want to return the Person object and then combine them. I'd like to (if it is possible) just combine it all in one line with chaining. I've tried several ways and can't get it to compile.
Edit
What original prompted me to want to do this was to avoid calling the GetPerson method 2x when using a concatenation approach to getting the full name (when not just creating a variable for this purpose). As was pointed out in the comments by Servy, this is really what variables are for and, as was also pointed out by O. R. Mapper, what I was looking for does not appear to be supported by C# at this time.
Well if you really want to do that in one line, you can use extension method which will apply to any object, like this:
public static class Extensions {
public static TResult Select<T, TResult>(this T target, Func<T, TResult> selector) {
return selector(target);
}
}
And then:
GetPerson(1).Select(p => p.firstName + " " + p.lastName);
You can use string.format
Person person = GetPerson(someId);
string.Format("{0} {1}", person.firstName, person.lastName);
STart with answering the question: How would the program consume the chained together first and last names?
For starters, you could
Create another field
string FullName
{
get
{
return this.firstName + " " + this.lastName;
}
}
Pros: It is readonly and solely based on the values in the class.
Cons: It is another field and causes you to violate the Single Responsibility Principle (meaning a different reason for the class to change, in this case formatting versus a data container).
Create a separate class that implements the Decorator Pattern that would then change the appearance (formatting) of the Person class to whatever you like. For example:
public interface IPersonFormatter
{
string asFullName(); // Returns "firstName lastName";
string asCSVRecord(); // Returns "id,firstName,lastName" to be imported to Excel
}
public class ConcretePersonFormatter : IPersonFormatter
{
//Members
private Person _personInstance;
public ConcretePersonFormatter(Person p)
{
_personInstance = p;
}
//IPersonFormatter implementation
string asFullName()
{
return _personInstance.firstName + " " + _personInstance.lastName;
}
string asCSVRecord()
{
return _personInstance.id + "," + _personInstance.firstName + "," + _personInstance.lastName;
}
}
Then create a ConcretePersonFormatter instance, and pass your instance of Person to it, then call the methods shown above
As I understood what you mean you can make property on your person class
string fullname
{
get
{
return firstName + " " + lastName;
}
}
So it would be:
GetPerson(someId).fullname;
Im quietly confuse on what is the difference between this code
class Person
{
private string name = "N/A";
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
}
and this code
class Person
{
public string Name { get; set; }
}
Can anyone help me to explain their use, and when they are being used. The advantage and disadvantage. Thanks!
these two pieces of code are exactly the same. When you write the second piece of code the c# compiler actually translates it to the first. It's just a quicker way to write and read it.
However this being said the first example has its uses.
For example if you would like to change the name value in any way before it was set you would have to use the first example.
For example:
class Person
{
private string name = "N/A";
public string Name
{
get
{
return name;
}
set
{
name = "My name is:" + value;
}
}
}
public String Name { get; set; }
Above is a short hand way to write a property and are called automatically implemented properties (AIPs). C# compiler will automatically create a private field for these behind the scenes.
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; }