I have a property where I want to convert the values systematically and I have a very large set of properties, so rather than have the following:
class myClass
{
private Double _Length;
public Double Length { get { return convert(_Length); } set { _Length = convertBack(value); }}
private Double _Height;
public Double Height{ get { return convert(_Height); } set { _Height= convertBack(value); }}
private Double _Width;
public Double Width{ get { return convert(_Width); } set { _Width= convertBack(value); }}
...
Double convert(Double base_value) { do work to return converted_value; }
Double unconvert(Double converted_value) { to work to return base_value; }
}
I would like to do something like this to reduce code pollution and redundancy
class myBaseClass
{
class DoublePropertyConverter extends Property
{
public Double get { return convert(this); }
public Double set { this = unconvert(value); }
}
Double convert(Double base_value) { do work to return converted_value; }
Double unconvert(Double converted_value) { to work to return base_value; }
}
class myClass : public myBaseClass
{
[DoublePropertyConverter]
public Double Length { get; set;}
[DoublePropertyConverter]
public Double Height{ get; set;}
[DoublePropertyConverter]
public Double Width{ get; set;}
...
}
Is this, or something like it, at all possible?
There's no way to "extend a property" in the way you're describing, no.
But it's easy enough to create a new type which represents conversions from and two some other value. Types like DateTime and TimeSpan are all just wrappers around a long that handle conversions to different semantic values for you, for example. Honestly it sounds like you should have a new type, because you've got a value that a consumer wants to treat in one way, but that is actually represented in memory as something else, and types are great at accomplishing just that in many situations that goes beyond the scope of getting and setting property values.
public class Foo
{
public Foo(double value)
{
underlyingValue = FromDouble(value);
}
private readonly object underlyingValue;
public double Value => ToDouble(underlyingValue);
public static implicit operator double(Foo foo) => ToDouble(foo.underlyingValue);
public static implicit operator Foo(double value) => new Foo(value);
private static double ToDouble(object underlyingVvalue)
{
throw new NotImplementedException();
}
private static object FromDouble(double value)
{
throw new NotImplementedException();
}
}
The underlying field in the type can be whatever you want that you're converting to/from, and you can then define your conversion logic in just one place.
Related
I'm trying to make a chemistry equation balancer thingy. For that I made a class Element:
class Element
{
public elemEnum ElemType {get; set;}
public double Amount {get; set;} // How many atoms of this type in the formula
}
*elemEnum is an Enum of all the chemical elements.
I wanted to make the set for ElemType parse a string to the enumeration, but since set can only take in values of the same type as value I decided to add a method:
public void SetElemType(string type)
{
this.ElemType = (elemEnum)Enum.Parse(typeof(elemEnum), type);
}
Is there an option to have the ElemType property be only set-able by the SetElemType method without having to make it private and adding a GetElemType method?
Since the most obvious solution from the comments has not been written as an answer:
Use a private setter.
class Element
{
public ElemEnum ElemType {get; private set;}
public double Amount {get; set;}
public void SetElemType(string type)
{
this.ElemType = (ElemEnum)Enum.Parse(typeof(ElemEnum), type);
}
}
This way, ElemType can only be set from within your own class.
without having to make it private
Well, you could create a workaround solution by adding a bool field to your class and modifying the property a little bit.
class Element
{
private bool _elemCanBeSet = false;
private elemNum _elemType;
public elemEnum ElemType
{
get { return _elemType; }
set { if (_elemCanBeSet) _elemType = value; }
}
public double Amount {get; set;} // How many atoms of this type in the formula
public void SetElemType(string type)
{
_elemCanBeSet = true;
this.ElemType = (elemEnum)Enum.Parse(typeof(elemEnum), type);
_elemCanBeSet = false;
}
}
This solution may confuse the developer using your class, because setting the property will have no effect. It is much better to use a private setter for your task, as stated by others. I just wanted to show an alternative approach.
As already was pointed, you can use private setter, alternatively you can use readonly property with public getter that works with field and method to modify this field :
class Element
{
private elemEnum _elemType;
public elemEnum ElemType { get { return _elemType; } }
public void SetElemType(string type)
{
this._elemType = (elemEnum)Enum.Parse(typeof(elemEnum), type);
}
public double Amount {get; } // How many atoms of this type in the formula
}
While it is practically the same as property with private setter it uses a slightly different approach...
Well if you really want to allow only one(!) method to change value you can use reflection and add class that envelopes your enum :
class MyElemSetter
{
private readonly elemEnum elem;
public MyElemSetter(elemEnum e, Action helperAction)
{
MethodInfo callingMethodInfo = helperAction.Method;
if (helperAction.Method.Name.Contains("<SetElemType>")) elem = e;
}
public static implicit operator elemEnum(MyElemSetter e)
{
return e.elem;
}
}
class Element
{
private MyElemSetter _elemType;
public elemEnum ElemType { get { return _elemType; } }
public void SetElemType(string type)
{
this._elemType = new MyElemSetter((elemEnum)Enum.Parse(typeof(elemEnum), type), () => { });
}
public double Amount { get; set; } // How many atoms of this type in the formula
}
I am trying to make a Money datatype (like int, string) in C#. However I can't seem to work out how to use it without the new Modifier. The class cannot be static as it has to be assigned to. I figured there must be a way, here is the code I have for the class, I may be doing this completely wrong.
public class Money {
private float _raw;
public float Raw {
get { return _raw; }
set { _raw = value; }
}
public string Pound {
get { return "£" + string.Format("{0:0.00}", _raw); }
}
}
Then I have the class I am calling it in and would like to just use:
private Money _money;
Instead of:
private Money _money = new Money();
Sorry if this is a stupid question but I couldn't find anything online nor could I figure it out myself.
You'll have to new it up somewhere. If you don't want to do it in the member declaration, then do it in the class constructor:
public MyClass()
{
_money = new Money();
}
An alternative solution involves using a factory method of some kind.
public class Money {
private float _raw;
public float Raw {
get { return _raw; }
set { _raw = value; }
}
public string Pound {
get { return "£" + string.Format("{0:0.00}", _raw); }
}
public static Money From(float val)
{
Money x = new Money();
x.Raw = val;
return x;
}
}
usage:
Money m = Money.From(9.95);
Using impilicit operator will allow you to set it like primitive data type.
http://haacked.com/archive/2012/09/30/primitive-obsession-custom-string-types-and-self-referencing-generic-constraints.aspx
public class Money
{
private float _raw;
public float Raw
{
get { return _raw; }
set { _raw = value; }
}
public string Pound
{
get { return "£" + string.Format("{0:0.00}", _raw); }
}
public static implicit operator Money(float value)
{
return new Money(){Raw = value};
}
}
Then you can use it like this.
Money m = 12;
Console.Write(m.Raw);
If you do not want to use property Raw to assign value you can make a operator overload, something like that:
public static implicit operator Money(Double value)
{
var money = new Money();
money.Raw = value;
return money;
}
And then in the calling code:
Money money = 10d;
But IMHO, i don't see any advantage in doing that, if you really need a muttable type, there should be no problem calling 'new' to instantiate it.
Adding a private constructor would prevent outsiders from "newing up" an instance... but then you also need to write a factory method or something to create it (in your class so that it has access to the private constructor). Otherwise your class is pretty useless!
That said, maybe if we knew why you didn't want to be able to "new up" an instance, we might be able to provide some tips.
Suppose that the scenario doesn't allow to implement an immutable type. Following that assumption, I'd like opinions / examples on how to properly design a type that after it's consumed, becomes immutable.
public class ObjectAConfig {
private int _valueB;
private string _valueA;
internal bool Consumed { get; set; }
public int ValueB {
get { return _valueB; }
set
{
if (Consumed) throw new InvalidOperationException();
_valueB = value;
}
}
public string ValueA {
get { return _valueA; }
set
{
if (Consumed) throw new InvalidOperationException();
_valueA = value;
}
}
}
When ObjectA consumes ObjectAConfig:
public ObjectA {
public ObjectA(ObjectAConfig config) {
_config = config;
_config.Consumed = true;
}
}
I'm not satisfied that this simply works, I'd like to know if there's a better pattern (excluded, as said, making ObjectAConfig immutable by design from begin).
For example:
can make sense define a monad like Once<T> that allow the wrapped value to be initialized only once?
can make sense define a type that returns the type itself changing a private field?
What you are implementing sometimes goes under the name "popsicle immutability" - i.e. you can freeze it. Your current approach will work - indeed I use that pattern myself in numerous places.
You can probably reduce some duplication via something like:
private void SetField<T>(ref T field, T value) {
if (Consumed) throw new InvalidOperationException();
field = value;
}
public int ValueB {
get { return _valueB; }
set { SetField(ref _valueB, value); }
}
public string ValueA {
get { return _valueA; }
set { SetField(ref _valueA, value); }
}
There is another related approach, though: a builder. For example, taking your existing class:
public interface IConfig
{
string ValueA { get; }
int ValueB { get; }
}
public class ObjectAConfig : IConfig
{
private class ImmutableConfig : IConfig {
private readonly string valueA;
private readonly int valueB;
public ImmutableConfig(string valueA, int valueB)
{
this.valueA = valueA;
this.valueB = valueB;
}
}
public IConfig Build()
{
return new ImmutableConfig(ValueA, ValueB);
}
... snip: implementation of ObjectAConfig
}
Here there is a truly immutable implementation of IConfig, and your original implementation. If you want the frozen version, call Build().
I'm experimenting with an API for publishing values at a given time (tuples of value and time). These samples will be used by a data viewer (e.g. a graph).
I want to associate the value with a Quantity and a Unit, for example length in meters. That way my "viewer" can scale it appropriately.
I'm looking for a sort of hierarchical enum, like this:
enum Quantity
{
Mass.Kg,
Mass.g,
Length.m,
Length.mm
}
But this doesn't exist in C#.
I'm not sure the best pattern to express this and I've come up with the following. Is there a recognised, or better way to do this?
using System;
using Moq;
namespace ConsoleApplication26
{
class Program
{
static void Main(string[] args)
{
//use a Mock to play with the API
Mock<ITelemetryPublisherFactory> mockTelemetryPublisherFactory = new Mock<ITelemetryPublisherFactory>();
var telemetryPublisherFactory = mockTelemetryPublisherFactory.Object;
//example usages
var massTelemetryPublisher = telemetryPublisherFactory.GetChannelSamplePublisher<Double>("My Mass", Mass.Kg);
massTelemetryPublisher.PublishChannelSampleAtTimeNow(83.4);
var lengthTelemetryPublisher = telemetryPublisherFactory.GetChannelSamplePublisher<Int32>("My Height", Length.μm);
lengthTelemetryPublisher.PublishChannelSampleAtTimeNow(1800000);
//10 years time..
lengthTelemetryPublisher.PublishChannelSampleAtTimeNow(1800000);
massTelemetryPublisher.PublishChannelSampleAtTimeNow(120.1);
}
}
public interface ITelemetryPublisherFactory
{
ITelemetryPublisher<T> GetChannelSamplePublisher<T>(String channelName, Quantity quantity);
}
public interface ITelemetryPublisher<T>
{
void PublishChannelSampleAtTimeNow(T sampleValue);
}
public abstract class Quantity {}
public class Mass : Quantity
{
private enum Unit
{
g,
Kg
}
private readonly Unit _unit;
private Mass(Unit unit)
{
_unit = unit;
}
public static Quantity Kg {get { return new Mass(Unit.Kg); }}
public static Quantity g { get { return new Mass(Unit.g); } }
public override string ToString()
{
return String.Format("Mass.{0}", _unit);
}
}
public class Length : Quantity
{
private enum Unit
{
m,
mm,
μm,
beardSecond
}
private readonly Unit _unit;
private Length(Unit unit)
{
_unit = unit;
}
public static Quantity m { get { return new Length(Unit.m); } }
public static Quantity mm { get { return new Length(Unit.mm); } }
public static Quantity μm { get { return new Length(Unit.μm); } }
public static Quantity beardSecond { get { return new Length(Unit.beardSecond); } }
public override string ToString()
{
return String.Format("Length.{0}", _unit);
}
}
}
I think it's better to create a Unit class for the unit of measure and a Quantity class that associates a unit of measure with an amount. Look at the Quantity pattern for the idea. Since you also want to record the "type" of the unit of measure, you could create a UnitType class that records that information:
public sealed partial class UnitType {
public string Name { get; private set; }
public UnitType(string name) {
Name = name;
}
}
public sealed partial class Unit {
public string Name { get; private set; }
public UnitType Type { get; private set; }
public Unit(string name, UnitType type) {
Name = name;
Type = type;
}
}
(You should make them proper value types by overriding Equals and GetHashCode)
The Unit class can be extended to provide for e.g. conversions, compound units, formatting and parsing.
Then, you can define the common cases inside the classes:
public partial class UnitType {
public static readonly UnitType Mass = new UnitType("Mass");
public static readonly UnitType Length = new UnitType("Length");
}
public partial class Unit {
public static readonly Unit Grams = new Unit("g", UnitType.Mass);
public static readonly Unit Kilos = new Unit("kg", UnitType.Mass);
// ...
}
Or define your "hierarchies" with static classes:
public static class Mass {
public static readonly UnitType Type = new UnitType("Mass");
public static readonly Unit Grams = new Unit("g", Type);
public static readonly Unit Kilos = new Unit("kg", Type);
...
}
public static class Length ...
The Quantity class would also be an immutable value type (just showing its usage):
var eniacWeight = new Quantity(27, Mass.Tons);
Or you could use extension methods to create Quantitys:
var eniacWeight = 27.Tons();
(from ENIAC)
This is not possible. Enums are primitive types and cannot inherit from other enums, as inheritance is a property of objects.
Hierarchical enum isn't possible, as noted above. If you're exclusively using metric, though, you can utilise standard prefixes if it helps.
enum MeasurementUnits
{
Gram,
Metre,
Litre,
Hectare
// etc
}
enum MeasurementPrefix
{
Milli,
Natural,
Kilo,
Mega
// etc
}
This may not be precisely what you want, but it will provide the type of 'grouping' that you might be looking for (e.g. group measurements that are about length, weight etc by checking their 'units' value).
Your suggested approach seems reasonable to me, and I use something similar in a project of mine. However, I keep the actual value part of the object, and I use struct instead of class, since they are naturally value types. Inheritance is not necessary here (and not possible with structs, anyways), so I use an interface to create a contract and act as a constraint when needed (I called it IUnitOfMeasure).
I do not recommend creating one enum with all the units of the various types of measurement combined; it is hell validating the unit to make sure someone didn't reference a Mass unit when working with Length.
public interface IUnitOfMeasure<TThis>
where TThis : IUnitOfMeasure<TThis>
{
TThis ConvertTo(TThis value);
}
public struct Mass : IUnitOfMeasure<Mass>
{
public enum Units
{
Gram,
Kilogram
}
private double _value;
private Mass.Units _unit;
public double Value { get { return _value; } }
public Mass.Units Unit { get { return _unit; } }
public Mass(double value, Mass.Units unit)
{
_value = value;
_unit = unit;
}
public Mass ConvertTo(Mass value)
{
switch(value.Unit)
{
case Units.Gram:
return new Mass(Unit == Units.Gram ? Value : Value/1000, Units.Gram);
case Units.Kilogram:
return new Mass(Unit == Units.Gram ? Value*1000 : Value, Units.Kilogram);
default:
throw new NotImplementedException();
}
}
public override string ToString()
{
return string.Format("{0} {1}", Value, Unit);
}
public static readonly Mass G = new Mass(0, Units.Gram);
public static readonly Mass Kg = new Mass(0, Units.Kilogram);
}
Usage:
var kg = new Mass(5.0, Mass.Units.Kilogram);
Console.WriteLine(kg); // writes "5 Kilogram"
var g = kg.ConvertTo(Mass.G);
Console.WriteLine(g); // writes ".005 Gram"
If you don't care about keeping the value, and just want to keep enum/static values in a central place:
public static class UnitOfMeasure
{
public enum Mass
{
Gram,
Kilogram
}
public enum Length
{
Meter,
Kilometer
}
// etc.
}
Usage: var unit = UnitOfMeasure.Mass.Kilogram;
You cannot introduce inheritance with enums. Enums are just a convenience mechanism to allow you to use meaningful textual identifiers in your code. From The code you have, I suggest you either use an enum like;
public enum UnitOfMeasure
{
MassGrams,
MassKg,
LengthMM,
LengthCM,
. . .
}
Or split it out to where it's appropriate, so that Mass and Length are defined separately for example.
The 'inheritance' is just something you've introduced in your thinking about this problem, but it isn't necessary to your solution. When you want to deal with Mass, you only look at the flags/enums appropriate to mass.
Is it possible to set or override the default state for a structure?
As an example I have an
enum something{a,b,c,d,e};
and a structure that links 2 values for that enum
struct SomethingData
{
something type;
int Value;
double Multipler;
SomethingData(something enumVal, int intVal, double DblVal) {...}
}
But can I specify that the default state is
SomethingData(something.c,0,1);
Struct constructors are similar to
class constructors, except for the
following differences:
Structs cannot contain explicit
parameterless constructors. Struct
members are automatically initialized
to their default values. A struct
cannot have an initializer in the
form: base (argument-list).
http://msdn.microsoft.com/en-us/library/aa288208(v=vs.71).aspx
So, short answer, no you can't override the default constructor (every struct has a parameterless constructor and you can't hide it or override it)...
You can't. Structs always have a default constructor that sets every member to its default value (null for reference types, 0 for numeric types, false for bools, etc.) This behavior cannot be changed.
You can't override the default (parameterless) constructor for a struct. You can only add new constructors, which take parameters.
http://csharp.2000things.com/2010/10/03/108-defining-a-constructor-for-a-struct/
Creating a class object will cause all of the instance fields to come into existence before anything--even the class constructor--can access it, and allocating an array will cause all of its elements to exist before anything can access the array. Both of these actions will cause all of the memory allocated to those fields or elements to be zeroed out without regard for the data types to be stored therein.
When a class-type storage location comes into existence, it will initially hold a null reference. When a structure-type storage location comes into existence, all of its fields (and any fields of structures within it) will do so simultaneously. Unlike class object instances which can only come into existence by using a constructor, structure-type storage locations are brought into existence without using any of the structure's own code. Consequently, the structure's definition will have no say in what should happen when "instances" [i.e. struct-type storage locations] come into existence.
A struct is, fundamentally, a collection of fields bound together with duct tape. If a struct is supposed to behave like something else, it should typically make its fields private and pretend to be immutable [even though struct assignment actually mutates the destination struct by overwriting all its fields with the corresponding values from the source, and the struct definition gets no say in the matter]. If, however, a struct is supposed to encapsulate a fixed set of related but independent values (e.g. the coordinates of a point), which may independently accommodate any combination of values which are legal for their respective types, a struct should simply expose its fields publicly. Some people may whine about "mutable structs are evil", but the evils only apply when invoking self-mutating methods on a struct. Structs which expose their state as fields behave like collections of variables stuck together with duct tape. If what one needs is a collection of variables stuck together with duct tape, trying to make a struct pretend to be immutable will simply make it harder to program with.
There is a workaround to make this happen by using custom Property getters. Observe:
public struct Foostruct
{
private int? _x;
private int? _y;
public int X
{
get { return _x ?? 20; } // replace 20 with desired default value
set { _x = value; }
}
public int Y
{
get { return _y ?? 10; } // replace 10 with desired default value
set { _y = value; }
}
}
This will only work for value types (which can be wrapped with nullable) but you could potentially do something similar for reference types by wrapping them in a generic class like below:
public class Wrapper<TValue>
{
public TValue Value { get; set; }
}
public struct Foostruct
{
private Wrapper<Tick> _tick;
public Tick Tick
{
get { return _tick == null ? new Tick(20) : _tick.Value; }
set { _tick = new Wrapper<Tick> { Value = value }; }
}
}
Somewhat related: I've often wanted to use the new object initializer syntax with an immutable value type. However, given the nature of a typical immutable value type implementation, there is no way to utilize that syntax, since the properties are read-only.
I've come up with this approach; In my opinion this still satisfies the immutability of the value type, but allows the code that is responsible for instantiating the value type greater control over the initialization of the internal data.
struct ImmutableValueType
{
private int _ID;
private string _Name;
public int ID
{
get { return _ID; }
}
public string Name
{
get { return _Name; }
}
// Infuser struct defined within the ImmutableValueType struct so that it has access to private fields
public struct Infuser
{
private ImmutableValueType _Item;
// write-only properties provide the complement to the read-only properties of the immutable value type
public int ID
{
set { _Item._ID = value; }
}
public string Name
{
set { _Item._Name = value; }
}
public ImmutableValueType Produce()
{
return this._Item;
}
public void Reset(ImmutableValueType item)
{
this._Item = item;
}
public void Reset()
{
this._Item = new ImmutableValueType();
}
public static implicit operator ImmutableValueType(Infuser infuser)
{
return infuser.Produce();
}
}
}
class Program
{
static void Main(string[] args)
{
// use of object initializer syntax made possible by the Infuser type
var item = new ImmutableValueType.Infuser
{
ID = 123,
Name = "ABC",
}.Produce();
Console.WriteLine("ID={0}, Name={1}", item.ID, item.Name);
}
}
Each time you get/set property you need to set default value call InitDefaultValues() method
private string _numberDecimalSeparator;
public string NumberDecimalSeparator
{
get
{
InitDefaultValues();
return _numberDecimalSeparator;
}
set
{
InitDefaultValues();
_numberDecimalSeparator = value;
}
}
...
private void InitDefaultValues()
{
if (!_inited)
{
_inited = false;
var ci = CultureInfo.CurrentCulture;
_numberDecimalSeparator = ci.With(x => x.NumberFormat).Return(x => x.NumberDecimalSeparator, ".");
...
}
}
Kinda dumb, but works
public readonly static float default_value = 1;
public struct YourStruct{
public float yourValue{
get {
return _yourValue + default_value;
}
set {
_yourValue= value - default_value;
}
}
public float _yourValue;
}
My solution. It works as well.
public struct DisplayOptions
{
public bool isUpon;
public bool screenFade;
public static DisplayOptions Build()
{
// Return default value
return new DisplayOptions(true, true);
}
DisplayOptions(bool isUpon, bool screenFade)
{
this.isUpon = isUpon;
this.screenFade = screenFade;
}
public DisplayOptions SetUpon(bool upon)
{
this.isUpon = upon;
return this;
}
public DisplayOptions SetScreenFade(bool screenFade)
{
this.screenFade = screenFade;
return this;
}
}
Use default value
// Use default
UIMaster.Instance.StartScreen("Screen 2", DisplayOptions.Build());
// Use custome
UIMaster.Instance.StartScreen("Screen 2", DisplayOptions.Build().SetScreenFade(false));
UIMaster.Instance.StartScreen("Screen 2", DisplayOptions.Build().SetUpon(false));
this should work
public struct MyStruct
{
private string myName;
private int? myNumber;
private bool? myBoolean;
private MyRefType myType;
public string MyName
{
get { return myName ?? "Default name"; }
set { myName= value; }
}
public int MyNumber
{
get { return myNumber ?? 42; }
set { myNumber = value; }
}
public bool MyBoolean
{
get { return myBoolean ?? true; }
set { myBoolean = value; }
}
public MyRefType MyType
{
get { return myType ?? new MyRefType(); }
set { myType = value; }
}
//optional
public MyStruct(string myName = "Default name", int myNumber = 42, bool myBoolean = true)
{
this.myType = new MyRefType();
this.myName = myName;
this.myNumber = myNumber;
this.myBoolean = myBoolean;
}
}
[TestClass]
public class MyStructTest
{
[TestMethod]
public void TestMyStruct()
{
var myStruct = default(MyStruct);
Assert.AreEqual("Default name", myStruct.MyName);
Assert.AreEqual(42, myStruct.MyNumber);
Assert.AreEqual(true, myStruct.MyBoolean);
Assert.IsNotNull(myStruct.MyType);
}
}
This may work...
public struct MyStruct
{
private bool _name;
public string myName
{
get { return (_name ? myName : "Default name"); }
set { _name = true; myName = value; }
}
private bool _num;
public int myNumber
{
get { return (_num ? myNumber : 42); }
set { _num = true; myNumber = value; }
}
private bool _bool;
public bool myBoolean
{
get { return (_bool ? myBoolean : true); }
set { _bool = true; myBoolean = value; }
}
private bool _type;
public MyRefType myType
{
get { return _type ? myType : new MyRefType(); }
set { _type = true; myType = value; }
}
}
Nevermind StackOverflowException
There is a workaround
public struct MyStruct
{
public MyStruct(int h = 1, int l = 1)
{
high = h;
low = l;
}
public int high;
public int low;
}