This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Difference between Property and Field in C#
public class Test
{
public bool testData1;
public string testData2;
}
or
public class Test
{
public bool TestData1 { get; set; }
public string TestData2 { get; set; }
}
or
public class Test
{
private bool testData1;
private string testData2;
public bool TestData1 { get { return testData1; } set { testData1 = value; } }
public string TestData2 { get { return testData2; } set { testData2 = value; } }
}
Which optimized code is better or unnecessary? And Why?
Isn't that last one holds a lot unnecessary data?
======= EDIT:
I think in that case:
public class Test
{
public Test(bool testData1)
{
this.testData1 = testData1;
}
private bool testData1;
public bool TestData1 { get { return testData1; } }
public string TestData2 { get; set; }
}
having fields in background is required. Isn't it?
You should not have public fields, use properties instead so you can change the internal implementation later on if neccessary - so 2) wins. 3) is just how auto properties are implemented under the hood so is equivalent to 2)
The second two are equivalent. Just different syntax for saying the same thing.
The first is different- it exposes fields, as opposed to properties. The difference between fields and properties has been covered ad nauseum on the web.
Second and third are same. First is bad, because if you change something (name, type) then you broke class interface.
Using number one in production code should be out of the question, because having public fields is a sure sign of poor use of encapsulation.
The numbers two and three are similar, with one important difference: if you plan to serialize your class, you should prefer #3, because you have tighter control over the variables that you can serialize. Other than that, #2 and #3 are identical. I always start with #2, and go for #3 only when necessary.
The first example is semantically different then the other two.
In the first example, you're using fields instead of properties.
The second example is equivalent to the third; the compiler will generate the backing fields itself. So, the second example is easier to read and imho cleaner.
regarding your editted question:
Not necessarly. You can perfectly do this:
public class MyClass
{
MyClass( bool x )
{
TestData1 = x;
}
public bool TestData1
{
get;
private set;
}
}
Related
I'm creating an app that returns a list of metals to use in various conditions. I have a Metal class then classes for each type of Metal like Steel, Aluminum, etc. If I have a list of different Steels, I want to first select the best ones based on a set of properties common to all Metals then do a second pass based on the unique properties of Steel. (This isn't my exact problem but my problem is analogous.)
I can't figure out how to pass a List<Steel> to the GetBest() method of the Metal class as shown below that takes its first argument of type List<Metal>. The code won't compile due to error at the line highlighted below with **: "Argument 1: cannot convert from 'System.Collections.Generic.List<Steel>' to 'System.Collections.Generic.List<Metal>'.
public class Metal {
public int PropA { get; set; }
public List<Metal> GetBest( List<Metal> list, int condition1 )
{
var best = new List<Metal>();
//Analysis code here...
return best;
}
}
public class Steel : Metal
{
public int PropB { get; set; }
public List<Steel> GetBest(List<Steel> list, int condition1, int condition2 ) {
var bestSteel = new List<Steel>();
//Do first pass selection based on properties of all metals.
**bestSteel = Metal.GetBest(list, condition1);**
//Do some additional analysis based to Steel's unique properties.
//Analysis code here...
return bestSteel;
}
You could use a constrained generic method:
public static List<T> GetBest<T>(List<T> list, int condition1) where T : Metal
{
var best = new List<T>();
// Analysis code here...
return best;
}
I'm going to answer a different question! A look at how I might approach this problem without confounding my objects (Metal, Steel) with my logic for picking the best metal based on some conditions:
public class Metal{}
public class Steel:Metal{}
public class MetalPickerContext
{
public int Condition1{ get;set;}
}
public class MetalPicker<TMetal, TContext>
where TMetal: Metal
where TContext: MetalPickerContext
{
public virtual IEnumerable<TMetal> GetBest(IEnumerable<TMetal> list, TContext context)
{
var result = new List<TMetal>();
// logic for picking the best metal based on Condition1
return result;
}
}
public class SteelPickerContext: MetalPickerContext
{
public int Condition2{get;set;}
}
public class SteelPicker : MetalPicker<Steel,SteelPickerContext>
{
public override IEnumerable<Steel> GetBest(IEnumerable<Steel> list, SteelPickerContext context)
{
var initialResult = base.GetBest(list,context);
// Having called the base logic apply more with reference to Condition2
return initialResult;
}
}
This compiles (as you can see here) and I could expand the example a bit given some more details to make it a working one. Let me know if that would help you.
I am looking at some legacy code and have come across an abstraction that has properties for each of its derived/concrete types. I cannot share the exact code but please imagine that instead of it being a simple operation that there are numerous operations that are much more complex.
I have not come across anything like this before and have a lot of questions? First, is this a pattern that I am not aware of? If so, what is it? Second question, how should I refactor this so that it follows solid principles?
I will try my best to come up with a better example if needed.
public enum ToolType
{
Unknown = 0,
HRMonitor,
Dumbell,
SomeForceDevice
}
public abstract class ToolData
{
private ToolData()
{
IsValid = false;
this.ToolType = ToolType.Unknown;
}
public ToolData(ToolType toolType)
{
this.ToolType = toolType;
}
public ToolType ToolType { get; }
public virtual bool IsValid { get; protected set; } = true;
public double LinkQuality { get; set; }
public NullToolDataValue NullData => this as NullToolDataValue;
public DumbellDataValue DumbellData => this as DumbellDataValue;
public HeartRateDataValue HRData => this as HeartRateDataValue;
public SomeForceDataValue SomeForceData => this as SomeForceDataValue;
}
public class NullToolDataValue : ToolData
{
public NullToolDataValue() : base(ToolType.Unknown)
{
IsValid = false;
}
}
public class DumbellDataValue : ToolData
{
public double WeightValue { get; private set; }
public DumbellDataValue(double weightValue) : base(ToolType.Dumbell)
{
this.WeightValue = weightValue;
}
public override string ToString()
{
return WeightValue.ToString(CultureInfo.InvariantCulture);
}
}
public class HeartRateDataValue : ToolData
{
public int HeartRate { get; private set; }
public HeartRateDataValue(int heartRate) : base(ToolType.HRMonitor)
{
this.HeartRate = heartRate;
}
public override string ToString()
{
return HeartRate.ToString(CultureInfo.InvariantCulture);
}
}
public class SomeForceDataValue : ToolData
{
public double LeftHandForceValue { get; private set; }
public double RightHandForceValue { get; private set; }
public int LeftHandPosition { get; private set; }
public int RightHandPosition { get; private set; }
public SomeForceDataValue(double lefthandValue, double rightHandValue, int leftHandPosition, int rightHandPosition) : base(ToolType.SomeForceDevice)
{
this.LeftHandForceValue = lefthandValue;
this.LeftHandPosition = leftHandPosition;
this.RightHandForceValue = rightHandValue;
this.RightHandPosition = rightHandPosition;
}
public override string ToString()
{
return $"{LeftHandForceValue.ToString(CultureInfo.InvariantCulture)}" +
$"| {LeftHandPosition.ToString(CultureInfo.InvariantCulture)}" +
$"| {RightHandForceValue.ToString(CultureInfo.InvariantCulture)}" +
$"| {RightHandPosition.ToString(CultureInfo.InvariantCulture)}";
}
}
It is being used/consumed via something like the below which it too is missing some inheritance and things for brevity:
public class DumbellExcercise
{
public void ToolDataReceived(ToolData data)
{
if (data?.DumbellData == null) return;
//add value to some collection
Collection.Add(data.DumbellData.WeightValue);
}
}
public class HRExcercise
{
public void ToolDataReceived(ToolData data)
{
if (data?.HRData == null) return;
//add value to some collection
Collection.Add(data.HRData.HeartRate);
}
}
Okay, I'm going to give a shot at answering - hopefully this will help.
First up, ToolData shouldn't contain any References/Enums/whatever that list its subtypes. So first on the chopping block: all the lambda properties that cast the object as a specific subtype. I can kinda understand the appeal - you know an instance of ToolType happens to be a FloobieTool, so you call instance.FloobieTool and magically get a FloobieTool cast. But... well, there are problems that come with it, not the least is that you're breaking Opened/Closed Principle. Nothing wrong with making the person calling the class cast it explicitly with (FloobieTool)instance if they know they're working with a FloobieTool.
Next up: the ToolType. Why do you need this? You can tell if your instance of ToolData is a FloobieTool by simply doing an 'is' check in an IF condition:
void SomeFunc(ToolData toolData)
{
if (!(toolData is FloobieTool)) throw new Exception("Non-Floobie!");
// more code
}
I mean, what does that enumeration actually get you? Because it has a definite cost: it has to be kept in-sync with the list of classes that implement ToolData.
Also, the part in ToolDataReceived() for each of those Exercise classes seems... weird. I mean, you've got an exercise, and you're passing in ToolData. Why are you storing the amount of the Dumbell exercise? As opposed to just storing the ToolData. I mean, you're going through quite a bit of testing/casting/etc, just to add the dumbbell weight to a Collection. Any reason you can't just store the ToolData instance and call it a day? If you really need to specifically store Dumbbell info, you could do something like:
public class DumbbellExercise
{
List<DumbbellDataValue> dumbbellData = new List<DumbbellDataValue>();
public void AddToolData(ToolData toolData)
{
if (toolData is DumbbellDataValue)
this.dumbbellData.Add((DumbbellDataValue)toolData);
}
}
Hopefully that helps - it's tough to go into too many details when we're working off an abstracted example of your actual problem :-)
Having seen your edits, I believe even more firmly that the way to refactor this code is to use pattern matching. Pattern matching requires at least C# 7.0 so I'll include an almost-as-good way to do it pre-7.0 versions.
Step 1
Mark the properties obsolete using ObsoleteAttribute and pass true for the error parameter.
[Obsolete("Use pattern matching instead.", true)]
public NullToolDataValue NullData => this as NullToolDataValue;
[Obsolete("Use pattern matching instead.", true)]
public DumbellDataValue DumbellData => this as DumbellDataValue;
[Obsolete("Use pattern matching instead.", true)]
public HeartRateDataValue HRData => this as HeartRateDataValue;
[Obsolete("Use pattern matching instead.", true)]
public SomeForceDataValue SomeForceData => this as SomeForceDataValue;
This will make it a compiler error to use them in any code processed by the compiler. If you're doing any reflection on them, you'll get a runtime exception instead (after step 3 is complete) if you don't also change that code.
Step 2
Modify every call site that uses those properties to use pattern matching instead. If all you're doing is what you showed in the question, is should be as simple as this:
public class DumbellExcercise
{
public void ToolDataReceived(ToolData data)
{
if (data is DumbellDataValue dumbell)
Collection.Add(dumbell.WeightValue);
// OR
if (!(data is DumbellDataValue dumbell))
return;
Collection.Add(dumbell.WeightValue);
}
}
The second variation is not as pretty because the condition has to be parenthesized before it can be negated (hey, at least VB has the IsNot keyword; go figure) but you get the same early return that the existing code has.
It looks like you're using at least C# 6.0 because you're using the null-coalescing operator (?.), but if you're not using at least 7.0, you can do this, instead:
public class DumbellExcercise
{
public void ToolDataReceived(ToolData data)
{
DumbellDataValue dumbell = data as DumbellDataValue;
if (dumbell != null)
Collection.Add(dumbell.WeightValue);
// OR
DumbellDataValue dumbell = data as DumbellDataValue;
if (dumbell == null)
return;
Collection.Add(dumbell.WeightValue);
}
}
Step 3
Remove the properties. If there are no more compiler errors, the properties aren't being used, so you're free to get rid of them.
Additional Note
The IsValid property has a strange duality to it. It can be assigned by the derived classes but it's also virtual so it can be overridden, too. You really should pick one. If it were my decision, I'd keep it virtual and make it read-only.
public abstract class ToolData
{
// Continue to assume it's true...
public virtual bool IsValid => true;
}
public class NullToolDataValue : ToolData
{
// ...and indicate otherwise as needed.
public override bool IsValid => false;
}
I asked myself for quite a while what advantages and disadvantages there are to using a property with the modifiers get and private set versus having a property that returns a private field.
Here's an example:
public bool Example { get; private set; }
and
private bool example;
public bool Example { get { return example; } }
What are the disadvantages and advantages of using one over the other?
1 less line of code. Other than that, they are the exact same functionality wise. It is syntactic sugar essentially.
There are couple of things, even though it's a syntax sugar with auto get set, in my opinion it depends on the design
public bool Example { get; set; }
The above line will have a private back field created by compiler which we don't have access. But if create a backing field we will have access of it and we can use it for null check like the below one
private bool example;
public bool Example
{
get
{
return example;
}
set
{
if(value != example)
{
example = value;
// here you can write some property change notifications or some other logic.
}
}
}
Either way end result is same
Prior to C# 6, the initialization of properties did not use backing fields to initialize default values.
In C#6, it uses the backing fields to initialize with new Auto initialization properties.
I'm curious why prior to C#6 IL uses the property definition to initialize. Is there a specific reason for this? or is it not implemented properly before C#6?
Before C# 6.0
public class PropertyInitialization
{
public string First { get; set; }
public string Last { get; set; }
public PropertyInitialization()
{
this.First = "Adam";
this.Last = "Smith";
}
}
Compiler Generated Code (IL representation)
public class PropertyInitialisation
{
[CompilerGenerated]
private string \u003CFirst\u003Ek__BackingField;
[CompilerGenerated]
private string \u003CLast\u003Ek__BackingField;
public string First
{
get
{
return this.\u003CFirst\u003Ek__BackingField;
}
set
{
this.\u003CFirst\u003Ek__BackingField = value;
}
}
public string Last
{
get
{
return this.\u003CLast\u003Ek__BackingField;
}
set
{
this.\u003CLast\u003Ek__BackingField = value;
}
}
public PropertyInitialisation()
{
base.\u002Ector();
this.First = "Adam";
this.Last = "Smith";
}
}
C#6
public class AutoPropertyInitialization
{
public string First { get; set; } = "Adam";
public string Last { get; set; } = "Smith";
}
Compiler Generated Code (IL representation)
public class AutoPropertyInitialization
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string \u003CFirst\u003Ek__BackingField;
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private string \u003CLast\u003Ek__BackingField;
public string First
{
get
{
return this.\u003CFirst\u003Ek__BackingField;
}
set
{
this.\u003CFirst\u003Ek__BackingField = value;
}
}
public string Last
{
get
{
return this.\u003CLast\u003Ek__BackingField;
}
set
{
this.\u003CLast\u003Ek__BackingField = value;
}
}
public AutoPropertyInitialization()
{
this.\u003CFirst\u003Ek__BackingField = "Adam";
this.\u003CLast\u003Ek__BackingField = "Smith";
base.\u002Ector();
}
}
I'm curious why prior to C#6 IL uses the property definition to initialize. Is there a specific reason for this?
Because setting a value through auto-property initialization and setting the value in a constructor are two different things. They have different behaviours.
Recall that properties are accessor methods which wrap around fields. So this line:
this.First = "Adam";
is equivalent to:
this.set_First("Adam");
You can even see this in Visual Studio! Try writing a method with the signature public string set_First(string value) in your class and watch as the compiler complains about you stepping on it's toes.
And just like methods, these can be overridden in child classes. Check out this code:
public class PropertyInitialization
{
public virtual string First { get; set; }
public PropertyInitialization()
{
this.First = "Adam";
}
}
public class ZopertyInitalization : PropertyInitialization
{
public override string First
{
get { return base.First; }
set
{
Console.WriteLine($"Child property hit with the value: '{0}'");
base.First = value;
}
}
}
In this example, the line this.First = "Adam" will call the setter in the child class. Because you're calling a method, remember? If the compiler were to interpret this method call as a direct call to the backing field, it wouldn't end up calling the child setter. The act of compiling your code would change the behaviour of your program. Not good!
Auto-properties are different. Lets change the first example by using an auto-property initializer:
public class PropertyInitialization
{
public virtual string First { get; set; } = "Adam";
}
public class ZopertyInitalization : PropertyInitialization
{
public override string First
{
get { return base.First; }
set
{
Console.WriteLine($"Child property hit with the value: '{0}'");
base.First = value;
}
}
}
With this code, the setter method in the child class will not be called. This is intentional. An auto-property initializer is designed to set the backing field directly. They look and behave like field initializers, which is why we can even use them on properties without setters, like this:
public string First { get; } = "Adam";
There's no setter method here! We would have to directly access the backing field to do this. Auto-properties allow programmers to create immutable values while still being able to benefit from nice syntax.
Keep in mind that values set as default for properties are not being set in the constructor (your code shows that: assigments, then constructor).
Now, the C# spec says that autoinitialization values are set before the constructor. This makes sense: When these values are set again in the constructor, they are overridden.
Now - before the constructor is called - there are no getter and setter methods initialized. How should they be used?
Thats why the (by then uninitialized backing-fields) are being initialized directly.
As hvd mentioned, there would also be a problem with virtual calls, but that they aren't even initialized is the main reason.
It still behaves the same way as before if you assign values in the constructor:
Example with property that is autoinitialized and changed in the ctor
Why isn't this being optimized out?
See my question about this topic:
But shouldn't it optimize that out?
It probably could, but only if that class doesn't inherit from another
class that uses that value in its constructor, it knows that it's an
auto-property and the setter doesn't do anything else.
That would be a lot of (dangerous) assumptions. The compiler needs to
check a lot of things before making an optimization like that.
Side note:
I assume you use some tool for seeing the compiler generated c# code - it's not entirely accurate. There's no accurate expression for the IL code that is being generated for a constructor - the ctor is not a method in IL, its something different. For the sake of understanding we can assume it is the same tho.
http://tryroslyn.azurewebsites.net/ as example has this comment:
// This is not valid C#, but it represents the IL correctly.
One way you can get the code as shown is that you have your C# 5 code like this:
public class Test : Base
{
public Test()
{
A = "test";
}
public string A { get; set; }
}
This will produce (IL) code like this:
public Test..ctor()
{
Base..ctor();
A = "test";
}
Your C# 6 code will look like this:
public class Test : Base
{
public Test()
{
}
public string A { get; set; } = "test";
}
Which produces (IL) code like this:
public Test..ctor()
{
<A>k__BackingField = "test";
Base..ctor();
}
Note that if you initialize your property specifically in the constructor, and have a getter/setter property, in C# 6 it will still look like the first piece of code in my answer above, whereas if you have a getter-only field it will look like this:
public Test..ctor()
{
Base..ctor();
<A>k__BackingField = "test";
}
So it is quite clear, your C# 5 code looked like the first piece of code above, and your C# 6 code looked like the second piece of code.
So to answer your question: Why does C# 5 and C# 6 behave differently in terms of how it compiles automatic property initialization? The reason is because you cannot do automatic property initialization in C# 5 or prior, and different code compiles differently.
The only time it makes a difference is if the property setter has more effects than simply setting the value. For auto-implemented properties, the only time that can happen is if they are virtual and overridden. In that case, calling the derived class method before the base class constructor has run is a very bad idea. C# goes through a lot of trouble to make sure you do not accidentally end up with references to not yet fully initialised objects. So it has to set the field directly to prevent that.
I'm assuming your C# 5.0 code looked like this:
class C
{
public C()
{
First = "Adam";
}
public string First { get; private set; }
}
And then in C# 6.0, the only change you made is to make First a get-only autoproperty:
class C
{
public C()
{
First = "Adam";
}
public string First { get; }
}
In the C# 5.0 case, First is a property with a setter and your use it in the constructor, so the generated IL reflects that.
In the C# 6.0 version, First does not have a setter, so the constructor has to access the backing field directly.
Both cases make perfect sense to me.
I am currently working on a game in XNA and I'm not sure on how I should go about doing the following...
I have a base class of buildings as such
public class BuildingsBase
{
private int _hp;
public int hp
{
get { return _hp; }
set { _hp= value; }
}
private int _woodRequired;
public int woodRequired
{
get { return _woodRequired; }
set { _woodRequired = value; }
}
}
I then have multiple subclasses for building types eg.
public class TownHall:BuildingsBase
{
public int foodHeld;
public TownHall()
{
foodHeld = 100;
woodRequired = 500;
}
}
My question is, what is the best way of setting the default values for building subclasses.
For example, the woodRequired for a townhall is set to 500 but at various places in code I need to access this value before I have an instance of townhall declared (When checking if there is enough wood to build).
I currently have a global array of default variables for each building type but im wondering if there is a better way of doing this.
if (Globals.buildingDefaults[BuildingType.Townhall].woodRequired < Globals.currentWood)
{
Townhall newTH = new Townhall();
}
Usually what happens is that they create a flyweight (see pattern). This object contains properties that are the same for every instance anyway. There's no need to change (or actually store) the required amount of wood for each instance separately.
In a very basic design it would look like:
class BuildingTemplate
{
public int WoodRequired { get; set; }
}
class Templates
{
public static BuildingTemplate TownHall { get; set; }
}
In the end you'd be calling a method like:
public bool CanBuildTownHall(Player player)
{
return player.HasEnoughResources(Templates.TownHall);
}
Of course, you can use a dictionary for template retrieval, and players shouldn't really know about building requirements. I'm just illustrating the pattern here.
If the player has enough resources, you can use the template to subtract the amount and create an actual instance of the TownHall. It's nice to have an reference to the actual template, because you'd probably be accessing other global properties that are valid for all TownHalls as well (such as audio/visuals/...).
class TownHall
{
public TownHall(BuildingTemplate template)
{
_template = template;
}
}