Reputation:
As you can see under I have create getter and setter for class property. I'm wondering, is it fine to set it up like I did under? I didn't use the private variable in the get, is it fine or should I use it? Could someone correct me how my class in this case, should look like, if my approach is wrong? The class is CloneAble
public int? Id { get; set; }
public string Code { get; set; }
private string _name;
public string Name
{
get
{
if (this.Id == null)
return null;
else
return this.Id+ "/" + this.Code;
}
set
{
if (this._name != value)
{
this._name= value;
}
}
}
public bool IsValid
{
get
{
if (this.Id == null)
return false;
else
return true;
}
}
The class is Cloneable:
public object Clone()
{
var elem= new Element();
this.SetPropertyValues(elem);
return elem;
}
private void SetPropertyValues(elem)
{
var propertyInfo = this.GetType().GetProperties().Where(p => p.CanWrite && (p.PropertyType.IsValueType || p.PropertyType.IsEnum || p.PropertyType.Equals(typeof(System.String))));
foreach (PropertyInfo property in propertyInfo)
{
if (property.CanWrite)
{
property.SetValue(elem, property.GetValue(this, null), null);
}
}
}
Upvotes: 0
Views: 1042
Reputation: 16049
I think you can get rid of your struggles by simplifying the Clone Method:
// Private parameterized CTOR
private Element( int id, string code )
{
this.Id = id;
this.Code = code;
}
// Simplyfied Clone
public object Clone()
{
return new Element(Id, Code);
}
Now you can have the readonly Property Name and Clone:
public string Name => $"{Id}/{Code}";
Upvotes: 1
Reputation: 1990
This code works, but what is the utility of _name
? You can set its value but not the opposite. In addition, creating IsValid
is not very useful, as Id
is a public attribute; you could simply create a method whose value is this.Id != wrongValue
and make Id
private.
The result would be the following:
private int Id { get; set; }
public string Code { get; set; }
private readonly int IMPOSSIBLE_ID = -1000;
private string _name;
public string Name
{
get {
return (this.Id == null) ? null : this.Id+ "/" + this.Code;
}
set {
if (this._name != value)
this._name= value;
}
}
public bool IsValid() => return this.Id != IMPOSSIBLE_ID;
UPDATE : now Id
is a nullable integer
private int? Id { get; set; }
public string Code { get; set; }
private string _name;
public string Name
{
get {
return (this.Id == null) ? null : this.Id+ "/" + this.Code;
}
set {
if (this._name != value)
this._name= value;
}
}
public bool IsValid() => return this.Id != null;
Upvotes: 0
Reputation: 186668
First of all int Id
can never be null
since int
is struct
; that's why this.Id == null
is always true
. You can either make Id
be nullable:
public int? Id { get; set; }
or change this.Id == null
into, say, this.Id == 0
// Let Id be nullable
public int? Id { get; set; }
public string Code { get; set; }
Since Name
can be easily computed, you don't want _name
. Another issue with Name
setter: you can assign, say, "bla-bla-bla"
to Name
then read it again
and get something unexpected:
var demo = MyClass();
// "0/"
Console.WriteLine(demo.Name);
demo.Name = "123/Test";
// "0/" instead of expected "123/Test";
Console.WriteLine(demo.Name);
That's why I suggest either to remove the setter:
public string Name {
get {
return Id.HasValue
? $"{Id}/{Code}"
: ""; // often, it's better return an empty string, not null
}
}
Or implement some kind of parsing:
public string Name {
get {
return Id.HasValue
? $"{Id}/{Code}"
: ""; // often, it's better return an empty string, not null
}
set {
if (string.IsNullOrEmpty(value)) {
Id = null;
Code = ""; // often, it's better return an empty string, not null
}
else {
string[] parts = string.Split(new char[] {'/'}, 2);
if (string.IsNullOrEmpty(parts[0])) {
Id = null;
Code = parts.Length > 1 ? parts[1] : "";
}
else if (int.TryParse(parts[0], out int id)) {
Id = id;
Code = parts.Length > 1 ? parts[1] : "";
}
else
throw new FormatException("Name is inincorrect format.");
}
}
}
Finally, IsValid
can be shortened into
public bool IsValid => Id.HasValue;
Upvotes: 0