Public fields vs. properties as they relate to constructors - c#

I'm pretty new to C# and scripting in Unity.
Up until now, when making a C# (Non-MB) class, I'd use the following pattern.
public class Item
{
public string itemName;
public Item(string newItemName)
{
itemName = newItemName;
}
}
and in some other script I could use Item rock = new Item("Rock"); or whatever.
Now, I'm using properties like the following.
public class Item
{
string itemName;
public string ItemName
{
get { return itemName; }
set { itemName = value; }
}
}
and in some other script I use Item rock = new Item(); rock.ItemName = "Rock";
Realistically, I use auto-implemented properties more often than not, and there are many more fields than just the item's name. When I used public fields, it was easy to set all these fields in the constructor. Now, I'm not sure how to, or if it's possible (if I want to keep them private). Therefore, I find myself having to use a default constructor and then settings all the fields with the properties like rock.ItemWeight = "1 lb" rock.ItemColor = "gray" rock.ItemType = "blunt instrument"...etc. for every item and field each time a new item is created. Is there a better way?

Never use public fields!
Set your brain to use auto-properties like this by default:
public string ItemName { get; } // without even the setter!
Only add the setter only when it is absolutely necessary for the class to be mutable.
Who says you can't set it in the constructor? Look:
public class Item
{
public string ItemName { get; }
public Item(string newItemName)
{
ItemName = newItemName;
}
}
You can also use an object initialisation block at the end:
public class Item
{
// setter is needed for this to work.
public string ItemName { get; set; }
}
var item = new Item() { ItemName = "" };
I just wanted to know how to set members within the constructor when those members are private.
Constructors are part of the class, so they can set private properties if they have a setter. It's just that outside the class, the properties are invisible.

You can use autoproperties and constructor like this:
public class Item
{
public string ItemName {get;set;}
public Item()
{
}
public Item(string itemName)
{
this.ItemName = itemName;
}
}
Then you can just do the following
Item item1 = new Item(value);
Or
Item item1 = new Item(){ItemName=value};

Your question actually boils down to wheather to set the members within the constructor or from the outside. As you´ve written in the comments you don´t wand an Item to exist without the members being set. So your decission depends on one single point: do you want to be able to modify the values which were set initially?
If you want this, the easiest way is to make those members publicily accessable and give them an initial value:
class Item
{
public string ItemName { get; set;} = "InitialValue";
}
or before C#6:
class Item
{
public string ItemName { get; set;}
public Item()
{
ItemName = "InitialValue";
}
}
If you don´t want to modify the members, you can use a private readonly backking-field instead:
class Item
{
private readonly string _itemName = "InitialValue";
public string ItemName { get { return _itemName; } }
}
Alternativly you can also create a default-constructor and set the initial value for ietmName there:
class Item
{
private readonly string _itemName;
public string ItemName { get { return _itemName; } }
public Item()
{
_itemName = "InitialValue";
}
}
You could also use a property which is readable from outside the class, but changable only within the class by using a private setter. However this is slightly different than using a private readonly backing-field, as in the latter case only the constructor is able to set the value, whilst in the former case evry code within your Item-class can change the value of the property.

Related

c# Set Parent class property in child setter

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.)

switch/case on viewmodel in controller, any refactoring advice?

I could use some advice on refactoring. In my application users are able to dynamically add new form fields; customfield. For each type (text, dropdown, checkbox, etc.) a ViewModel (TextBoxViewModel, DropDownViewModel, CheckboxViewModel, etc.) is defined.
When I post a form, the appropriate Edit action is executed and I read each customfield to store their values.
Currently the implementation works but is ugly; I switch/case/if/else through all ViewModel types and based on the type I execute the required logic.
This is the the current implementation:
private static void MapToModel(Ticket ticket, TicketViewModel model)
{
ticket.Id = model.Id;
ticket.Name = model.Name;
ticket.Attributes.Clear();
foreach (var cvm in model.Controls)
{
var attribute = new TicketAttribute
{
Id = cvm.Id,
Name = cvm.Name,
};
if (cvm is TextBoxViewModel)
{
attribute.Value = ((TextBoxViewModel) cvm).Value;
}else if (cvm is DropDownListViewModel)
{
attribute.Value = ((DropDownListViewModel)cvm).Values;
}
ticket.Attributes.Add(attribute);
}
}
And I would like to refactor this to something like this, but without putting all logic in the ViewModel. Best I could come up with is the visitor pattern where I would add a Accept method to the ViewModel class, and use visitors to execute the logic required:
This would still require the same switching logic on types in the AddAttribute method:
foreach (var cvm in model.Controls)
{
ticket.Attributes.AddAttribute(cvm);
}
This would require logic in the ViewModel class
foreach (var cvm in model.Controls)
{
ticket.Attributes.Add(cvm.AddAttribute);
}
I want to refactor this to create a more generic approach, so that in future when new types of fields are added I don't have to update all codes with new constructions to check for types.
[solution after the provided help]
I had to cast the object, I cannot use different returntypes in different implementations of IControlViewModel so that is one part I have to work around, but overall this is beautiful.
ticket.Attributes = model.Controls
.OfType<IControlViewModel>()
.Select(cvm => new TicketAttribute {
Id = cvm.Id,
Name = cvm.Name,
Value = (string)cvm.OutputValue
})
.ToList();
public interface IControlViewModel
{
string Id { get; }
string Name { get; }
object OutputValue { get; }
}
public abstract class ControlViewModel : IControlViewModel
{
public string Id { get; set; }
public abstract string Type { get; }
public string Label { get; set; }
public string Name { get; set; }
public bool Visible { get; set; }
public abstract object OutputValue { get; }
}
public class TextBoxViewModel : ControlViewModel
{
public override string Type
{
get { return "textbox"; }
}
public override object OutputValue
{
get
{
return Value;
}
}
public string Value {set; }
}
1) Create an interface which defines that you will have output value property on each of your view models
public interface IControlViewModel
{
object OutputValue{get;}
}
2) Implement interface in each of your viewmodels:
public TextBoxViewModel: IControlViewModel
{
...
public object OutputValue
{
get
{
//return whatever is your expected output value from control
return Value;
}
}
...
}
3) Then you can get all attributes with this single LINQ statement:
ticket.Attributes = model.Controls
.OfType<IControlViewModel>()
.Select(cvm => new TicketAttribute {
Id = cvm.Id,
Name = cvm.Name,
Value = cvm.OutputValue
})
.ToList();
4) This code will work fine even if you create new control types, just make sure to implement interface in your new viewmodels.

Return a List<SomeObject> without a certain property using Linq in c#?

I have an object containing different properties like the object below:
public class CompressedLogResponse
{
public string LoggerType { get; set; }
public int NumberOfRegisters { get; set; }
public int NewLogId { get; set; }
public DateTime LoggerAnnounceTime { get; set; }
public List<Log> Log{ get; set; }
}
How can I return a List of this objekt that does not include the List<Log> Log property?
Linq would be preffered
Thanks for any help that you can provide
You cannot just hide a property of a class (you declared it a as public)
Option 1:
Althought as Robson wrote you can set it null (thats not very reliable thaught cause nobody expects a class containing a property that is always null)
Option2:
If you consume the class on the same place use a anonymous type as Mez wrote, althought it sounds like you want to hide the Property from external usage. (I don't like the dynamic approach, the dynamic keyword was made for interop/DOM not for transporting anonymous types.)
Option3:
If you want a List of this type to be returned without the Log property, you have to create a new class (Inheritance is a good way to realize this):
public class CompressedLogResponseBase
{
public string LoggerType { get; set; }
public int NumberOfRegisters { get; set; }
public int NewLogId { get; set; }
public DateTime LoggerAnnounceTime { get; set; }
}
public class CompressedLogResponse : CompressedLogResponseBase
{
public List<Log> Log{ get; set; }
}
Now you can return a list of base items (that do not have a Log property at all)
public List<CompressedLogResponseBase> ReturnWithoutLog(IEnumerable<CompressedLogResponse> items)
{
return ((IEnumerable<CompressedLogResponseBase>)items).ToList();
}
If a IEnumerable as return type is suficient it becomes really easy
public IEnumerable<CompressedLogResponseBase> ReturnWithoutLog(IEnumerable<CompressedLogResponse> items)
{
return items
}
whith "does not include the List Log property" i guess you mean that the property "public List Log" will be blanked but still there, so you can just null that property out, because if you create an object that doesn't contain the "public List Log" property, than it will not be a "CompressedLogResponse" but will be another type.
List<CompressedLogResponse> listOne = new List<CompressedLogResponse>();
//....
//fill the listOne
//....
List<CompressedLogResponse> listWithoutListLog = (from item in listOne
select new CompressedLogResponse(
LoggerType = item.LoggerType,
NumberOfRegisters = item.NumberOfRegisters ,
NewLogId = item.NewLogId ,
LoggerAnnounceTime = item.LoggerAnnounceTime ,
Log= null)).ToList();
You can return an anonymous list of your original list like the following;
public static List<dynamic> Test() {
List<CompressedLogResponse> list = new List<CompressedLogResponse>();
var result = list.Select(x => new
{
x.LoggerAnnounceTime,
x.LoggerType,
x.NewLogId,
x.NumberOfRegisters
});
return result.ToList<dynamic>();
}
Take a look at the .Select(), and also the dynamic keyword.
Then to call it,
var x = Test();
foreach(dynamic o in x)
{
int NumberOfRegisters;
//You have 2 ways... either by
NumberOfRegisters = o.NumberOfRegisters;
// or reflection
NumberOfRegisters = o.GetType().GetProperty("NumberOfRegisters").GetValue(o, null);
}

Adding Tags and its respective value to an object

Let's assume we have a class called "Tag".
public class Tag
{
public string Name { get; private set; }
public string Description { get; private set; }
public Type Type { get; private set; }
public Tag(string name, string description, Type type)
{
this.Name = name;
this.Description = description;
this.Type = type;
}
}
An example of an instance of a Tag would be:
Tag weightTag = new Tag("Weight", "Weight of item in kg", typeof(double))
Next assume that I have another class which has a collection of these Tags which a value relevant to that object mapped to each individual tag in the collection.
public class Item
{
public string Id { get; private set; }
public string Name { get; private set; }
public string Description { get; private set; }
public Dictionary<Tag, object> Tags { get; private set; }
public Item(string name, string description)
{
this.Name = name;
this.Description = description;
this.Tags = new Dictionary<Tag, object>();
}
public void AddTag(Tag tag, object value)
{
Tags.Add(tag, value);
}
}
I like this method due to the fact that you can take some predefined tags from some where and then just assign a value.
Tag buildDateTag = TagProvider.GetByName("BuildDate");
Tag weightTag = TagProvider.GetByName("Weight");
item.AddTag(buildDateTag, new DateTime(2013,12,06);
item.AddTag(weightTag, 10.5);
The downside to this method is that there will be a lot of boxing/unboxing. For instance, if I have a collection of Item and I want to sum all the values of the tag corresponding to weight I'd have to do something like:
double totalWeight = 0d;
foreach (var item in items)
{
if (Tags.ContainsKey(weightTag))
{
totalWeight += (double)Tags[weightTag];
}
}
In this instance I happened to know that I'm going to cast to double so the only performance penalty was the unboxing. However there may be instances where I will need to get the type of the object from the Type member in the Tag object in order to figure out what the type of the value object is.
My question is do you think there is a better way to architect this in order to get rid of the need to rely on using objects and unboxing everything every time I want to use a value?
And although this should probably be a different question, in this usage should Tag be a struct rather than a class?
IMHO, you can use an interface that has some of the common properties for the objects that you are expecting to be as part of the objects that you can tag against.
In that case, you can accept any object that Implements your interface and hence, you will have a neat and a cleaner code
Sample :
class BuildDateTag : ITaggable
{
int id;
string name;
double weight;
}
this way, you can have the tags defined inside the Item class from
public Dictionary<Tag, object> Tags { get; private set; }
to public Dictionary<Tag,ITaggable> Tags{get;set;}
Consider this and post the queries and your feasibility w.r.to this suggestion

The right way to build a c#'s app (CF .NET 3.5), i need advice

Over the past two years I developed apps for the CF .NET 3.5 to be runned on warehouse's portable device(windows mobile).
From the beginning I just jumped into the process and made a lot of mistakes that I'm gradually correcting. What has came out are apps made in this way:
a main form to start the whole process which automatically creates a data-form, that will stay alive for the whole time. This data-form will keep all the datas that the user will insert or request from the server. The other forms are basically views of the data with methods to manipulate them.
It works but...am I doing this in the right way? Or maybe am I missing something really fundamental?
So, you created a data form, and you are using it like RAM. You never display the data, you simply store it there to access.
If someone ever has to take over your job (like you leave the company or die), they are going to hate you so bad.
A better technique would be to create a Class that houses all of this data.
The good part is, since you already have a data form, you probably already know how everything is organized!
Now, just use that knowledge of your data to create your class that you can read and write to.
If you have groups of similar items, create other classes that your main class will contain.
If you have several of these similar items, create publically accessible Lists of these items.
Make it as dead simple or as complex as you'd like!
Consider these classes, which are all generic enough to modify however you would need and demonstrate some extras added:
public class DataForm {
private GroupedItem m_item2;
public event EventHandler Item2Changed;
public DataForm() { // this is your constructor
Item1 = new GroupedItem();
Item2 = new GroupedItem();
ItemCollection = new GroupCollectionItems("Group1");
}
public float Value1 { get; set; }
public float Value2 { get; set; }
public GroupedItem Item1 { get; set; }
public GroupedItem Item2 {
get { return m_item2; }
set {
if (m_item2 != value) {
m_item2 = value;
if (Item2Changed != null) {
Item2Changed(this, EventArgs.Empty); // notify whoever is listening for the change
}
}
}
}
public GroupCollectionItems ItemCollection { get; set; }
}
public class GroupedItem {
public GroupedItem() { // this is your constructor
}
public string Name { get; set; }
public object Value { get; set; }
}
public class GroupCollectionItem {
private GroupCollectionItem() { // this is your constructor
}
public static GroupCollectionItem Create(string groupName, string itemName, object itemValue) {
var item = new GroupCollectionItem() {
Group = groupName,
Name = itemName,
Value = itemValue
};
return item;
}
public string Group { get; private set; }
public string Name { get; private set; }
public object Value { get; set; }
}
public class GroupCollectionItems : List<GroupCollectionItem> {
public GroupCollectionItems(string name) { // this is your constructor
Name = name;
}
public string Name { get; private set; }
}

Categories

Resources