I have one class :
public class Car
{
public string Color { get; set; }
public string Speed { get; set; }
public string Property3 { get; set; }
}
I want to set automatically the value of Property3 when property Color or Speed are updated
I want to set the value of Property3 with the concatenation of value Color and Speed separated with hyphen
What is the best way to do this ?
You can specify that in the getter of Property3 - something like this:
public string Property3
{
get { return $"{this.Color}-{this.Speed}"; }
}
I assume that you want Property3 to be read only so I omitted the setter in the sample above
you can set that getter property like this
public string Property3 {
get { return Color + "-" + Speed; }
}
You have two ways:
Update the dependent property within setters of speed and color:
private string _Color;
public string Color
{
get
{
return this._Color;
}
set
{
this._Color = value;
this.Property3 = $"{this.Color}-{this.Speed}";
}
}
private string _Speed;
public string Speed
{
get
{
return this._Speed;
}
set
{
this._Speed = value;
this.Property3 = $"{this.Color}-{this.Speed}";
}
}
public string Property3 { get; set; }
Concatenation within get of the dependent property:
public string Property3
{
get
{
return $"{this.Color}-{this.Speed}";
}
}
Conceptual difference is quite obvious: Do you want to be able to overwrite Property3 or should it be read only.
Related
I have an XML like this:
"<ArrayOfClsLog xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
<ClsLog>
<Subject>sth</Subject>
<Value>123456</Value>
<Comment>val</Comment>
</ClsLog>
</ArrayOfClsLog>"
and with this code I desterilize it:
var tmpSerializer = new XmlSerializer(typeof(ObservableCollection<ClsLog>));
tmpResult = tmpSerializer.Deserialize(tmpReader) as ObservableCollection<ClsLog>;
here is my ClsLog:
public class ClsLog
{
public string Subject { get; set; }
public string Value {get; set;}
public string Comment { get; set; }
}
Everything is fine except:
Big Problem
I want the content of value which can be a number like 123456 converts into 123,456
So I've changed Clslog to :
public class ClsLog
{
public string Subject { get; set; }
public string Value {
get
{
return decimal.Parse(Value.ToString()).ToString("N2", System.Globalization.CultureInfo.InvariantCulture);
}
set
{ }
}
public string Comment { get; set; }
}
But nothing changed, also I've tried to change tmpResult with LINQ:
tmpResult=tmpResult.ToList().ForEach(i => i.Value =
decimal.Parse( i.Value.ToString()).ToString("N2", System.Globalization.CultureInfo.InvariantCulture));
So bad exception happened and turned out I can't change it manually.
Question
How I can fix it? (make value from 123456 to 123.456)
You are declaring this property wrong.
public string Value //why a string why not a decimal?
{
get
{
// you have an infinite recursion here
return decimal.Parse(Value.ToString()).ToString("N2", System.Globalization.CultureInfo.InvariantCulture);
}
set { } // the setter is empty anyway so youcan't set it.
}
Instead try this
private decimal _value; // internal field
public decimal Value
{
get
{
return _value; // return internal field
}
set
{
_value = value / 1000; // set the internal field to the value / 1000
}
}
Veracode throws "Technology-Specific Input Validation Problems (CWE ID 100)" for a public string property in C#.
These are the formats I have tried already, and all give same flaw.
Option: 1
public string MyProperty { get; set; }
Option: 2
private string _myProperty;
public string MyProperty
{
get
{
return _myProperty;
}
set
{
_myProperty = value;
}
}
Option: 3
private string _myProperty;
public string MyProperty
{
get
{
return _myProperty ?? string.Empty;
}
set
{
_myProperty = value;
}
}
Can anyone tell why?
This URL has some information suggesting a potential fix to the flow:
https://learn.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/model-validation-in-aspnet-web-api
So, ultimately, the property just needs an attribute and it would look like this:
[Required]
public string MyProperty { get; set; }
This is the whole list of possible attributes from System.ComponentModel.DataAnnotations Namespace.
https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations(v=vs.110).aspx
I am total MVC newbie coming from 10 years of webforms. Here is the code I have inherited:
namespace sample.Models
{
public class Pages
{
public int PageID { get; set; }
public string FolderName { get; set; }
}
}
How can I apply a trim function to the "set" portion of this code? Right now it is allowing spaces at the end of foldername and I need to prevent that.
Okay I have incorporated the suggestions however the spaces are still getting saved.
Here are the UI/ vs Database. The UI is trimming properly but the full value with spaces is stored in the table:
You need a backing field:
public class Pages
{
public int PageID { get; set; }
private string _folderName;
public string FolderName
{
get { return _folderName; }
set { _folderName = value.Trim(); }
}
}
In the setter method we use the Trim string's method, which
Removes all leading and trailing white-space characters from the current String object.
For further info regarding this method, please have a look here.
What about this solution:
public class Pages
{
private string _folderName;
public int PageID { get; set; }
public string FolderName
{
get { return _folderName; }
set { _folderName = value?.Trim() ?? string.Empty; }
}
}
You may consider writing a custom extension method to call Trim only if the value of your string is not null:
public static class CustomExtensions
{
public static string TrimIfNotNull(this string value)
{
if (value != null)
{
value = value.Trim();
}
return value;
}
}
And then in your Pages class, something like
private string _folderName;
public string FolderName
{
get { return _folderName.TrimIfNotNull(); }
set { _folderName = value.TrimIfNotNull(); }
}
If you're using C#6, as mentioned by Jacob Krall, you can use the null conditional operator directly and not worry about the extension method:
public string FolderName
{
get { return _folderName; }
set { _folderName = value?.Trim(); }
}
The shorthand syntax for properties is only for when you want to provide a thin layer of abstraction on top of a field. If you want to manipulate the field within the getter or setter, you need to specify the backing field on your own.
namespace sample.Models
{
public class Pages
{
public int PageID { get; set; }
private string folderName;
public string FolderName
{
get { return folderName; }
set { folderName = value.Trim(); }
}
}
}
public class Pages
{
public int PageId { get; set; }
// you need a backing field then you can customize the set and get code
private string folderName;
public string FolderName
{
get { return this.folderName; }
// if the fileName can be set to null you'll want to use ?. or you'll get
// a null reference exception
set { this.folderName = value?.Trim(); }
}
}
See the code below.
//You can filter the entry before saving it into the database.
//About the null issue. You can use this.
if(String.IsNullOrEmpty(txtusername.Text))
{
throw new Exception("Cannot be blank!");
}
//You can filter the entry before saving it into the database
txtpageid.Text = book.PageID.Trim();
txtfoldername.Text = book.FolderName.Trim();
I have a c# object 'Product' with a property called: Offset
In the database the field is of type nvarchar(50)
I will be storing a JSON value in it such as the following: { "y": 0, "m": 0, "d": 0 }
I would like to know a good way of working with a property like this in my code. Here is how I currently am doing it:
public class Product
{
public int Id {get; set;}
public string Description {get; set;}
public decimal Price {get; set;}
public int OffsetYears { get; set; }
public int OffsetMonths { get; set; }
public int OffsetDays { get; set; }
public string Offset
{
get
{
Offset offset = new Offset()
{
Y = OffsetYears,
M = OffsetMonths,
D = OffsetDays
};
return JsonConvert.SerializeObject(offset);
}
set
{
OffsetObj offset = JsonConvert.DeserializeObject<Offset>(value);
OffsetYears = offset.Y;
OffsetMonths = offset.M;
OffsetDays = offset.D;
}
}
private class OffsetObj
{
public int Y { get; set; }
public int M { get; set; }
public int D { get; set; }
}
}
So then when I accept values from the User in the UI I would set the OffsetYears, OffsetMonths, and OffsetDays properties.. So in my repository I can just save Offset.
And when retrieving values from the database I will simply work with OffsetYears, OffsetMonths, and OffsetDays properties in my code.
Is there a better way to handle this sort of thing? I just feel like I am not utilizing all of my c# resources. Like what if another developer accidentally sets Offset through the code assuming any format of string can go in it.
Or am I better off just creating 3 separate integer fields in the database and avoiding all of this...
I would hold the values in a field of your private type. Consider this approach:
public class Product
{
private OffsetObj _offset = new OffsetObj();
public int Id { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int OffsetYears
{
get { return _offset.Y; }
set { _offset.Y = value; }
}
public int OffsetMonths
{
get { return _offset.M; }
set { _offset.M = value; }
}
public int OffsetDays
{
get { return _offset.D; }
set { _offset.D = value; }
}
public string Offset
{
get
{
return JsonConvert.SerializeObject(_offset);
}
set
{
_offset = JsonConvert.DeserializeObject<OffsetObj>(value);
}
}
private class OffsetObj
{
public int Y { get; set; }
public int M { get; set; }
public int D { get; set; }
}
}
This way, the field offset will hold the values for the offset.
Like what if another developer accidentally sets Offset through the code assuming any format of string can go in it.
JsonConvert will throw a JsonReaderException if trying to set the Offset property to a string that does not match JSON-format. In my opinion this is expected. To clarify further, you could name your property to OffsetJson.
However, I fail to see the benefit in this simple case to store your information as JSON. If you are using a relational database, you may as well just store your values in separate columns.
Im trying to set a parent class property in child property setter.
I have one main class :User, which has a child class LIST ArrayPositions, which in turn has a child class list of ExpressionMember.
Whenever the property ExpressionMemValue in ExpressionMember class is set, i want to update it's parent class ArrayPosition aswell.
However the current solution does not update the corresponding parent.
Here's the code:
public List<User> users = new List<User>();
public class User
{
public string ImageName { get; set; }
private string _PartName = "";
public string PartName
{
get
{
return this._PartName;
}
set {
_PartName=value;
}
}
public List <ArrayPosition> ArrayPositions { get; set; }
public override string ToString()
{
return this.PartName.ToString();
}
}
public class ArrayPosition:User
{
public string myArrayPos = "";
public string PartId { get; set; }
public string ArrayPos
{
get
{
return this.myArrayPos;
}
set
{
this.myArrayPos = value;
}
}
public List<ExpressionMember> ExpressionMembers { get; set; }
}
public class ExpressionMember : ArrayPosition
{
public string ExpressionMem { get; set; }
public string MyExpressionMemValye="";
public string ExpressionMemValue
{
get
{
return MyExpressionMemValye;
}
set
{
MyExpressionMemValye = value;
// this.ArrayPos = value; //set parent value, this will not update it
}
}
}
It would appear that you need to not use inheritance and instead use composition which you are kind of already doing. Try doing this instead. It's not perfect by any means but I'm trying not to change your general strategy too much.
public class User
{
public string ImageName { get; set; }
private string _PartName = "";
public string PartName
{
get
{
return this._PartName;
}
set {
_PartName=value;
}
}
public List <ArrayPosition> ArrayPositions { get; set; }
public override string ToString()
{
return this.PartName.ToString();
}
}
public class ArrayPosition
{
public string myArrayPos = "";
public string PartId { get; set; }
public string ArrayPos
{
get
{
return this.myArrayPos;
}
set
{
this.myArrayPos = value;
}
}
public List<ExpressionMember> ExpressionMembers { get; set; }
}
public class ExpressionMember
{
private ArrayPosition _parentArrayPosition;
public string ExpressionMem { get; set; }
public string MyExpressionMemValye="";
public string ExpressionMemValue
{
get
{
return MyExpressionMemValye;
}
set
{
MyExpressionMemValye = value;
this._parentArrayPosition.ArrayPos = value;
}
public ExpressionMember(ArrayPosition parent) {
_parentArrayPosition = parent;
}
}
}
You are definitely not using inheritance and composition correctly. You are looking to build a tree of objects where the object itself has child objects. Something that might clarify things in your mind is instead of calling them child/parent classes, refer to them as sub/super classes in the case of inheritance and parent/child objects in the case of composition. A parent object is an instance of a class that contains another instance of a class (child object). A subclass inherits the members of another class.
Your inheritance is very strange. The exact responsibilities of your classes are not clear to me.
Apart from that, you could protect the property ExpressionMembers by making it read-only. Implement a new method to add or remove elements. Add an event (e.g. ExpressionMemValueChanged) to ExpressionMember . This event is triggered when an item is added. Whenever an element is added or removed you register/deregister ArrayPosition to/from this event. Inside the event handler you can then set your ArrayPos value.
(You can use an ObservableCollection for your ExpressionMembers and react to the CollectionChanged event instead of writing a getter/setter.)