I'm trying to deserialize an XML string, where the value of an element, ain't within the scope of my Enum values.
Public enum MyEnum
{
Unknown,
Car,
Bicycle,
Boat
}
[SerializableAttribute()]
public class MyClass
{
private string _id;
private MyEnum _myEnum;
public string ID
{
get { return _id; }
set { _id = value; }
}
public MyEnum EnumValue
{
get { return _myEnum; }
set { _myEnum = value; }
}
public MyClass(string id)
{
this._id = id;
}
public MyClass() : this("") { }
}
If I try to deserialize following string (note Plane as enum value):
<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><MyClass><ID>1234567890123456789</ID><EnumValue>Plane</EnumValue></MyClass>
then my deserialize will thrown an exception, before it even hit my public field for EnumValue, with following exception message:
Instance validation error: 'Plane' is not a valid value for EnumValue
Is it possible to return a default value for EnumValue, if the value I try to parse in the XML ain't supported as a EnumValue??
Eg. in the case of the XML string provided here, the EnumValue should be set as 'Unknown'.
[XmlIgnore]
public MyEnum EnumValueReal
{
get { return _myEnum; }
set { _myEnum = value; }
}
public string EnumValue
{
get
{
return EnumValueReal.ToString();
}
set
{
MyEnum result = MyEnum.Unknown;
Enum.TryParse(value, true, out result);
EnumValueReal = result;
}
}
Other way around would be to declare EnumValue as string and parse value in EnumValue property to MyEnum in another property (with custom logic). Another property should be marked as not serializable.
public string EnumValue
{
get { return _myEnum; }
set { _myEnum = value; }
}
[NonSerialized]
public MyEnum EnumValueTyped {
get {
MyEnum value;
if (Enum.TryParse<MyEnum>(EnumValue, out value)) {
return value;
}
return MyEnum.Unknown;
}
set {
EnumValue = value.ToString();
}
}
Sometimes what happens is we do not take the update of the dlls or the projects we are referring in the project after making changes to the later and hence the parameter added/deleted does not get detected, thus throwing the same issue. Hence better take the updated dll and proceed.Can be a silly mistake but often committed. All the best :)
IMHO the most 'appropriate' solution would be to make EnumValue property nullable - since error you are getting (and MyEnum.Unknown) implies that it is possible for this property not to have a value...
Code would look following:
public enum MyEnum
{
Car,
Bicycle,
Boat
}
[Serializable()]
public class MyClass
{
private string _id;
private MyEnum? _myEnum;
public string ID
{
get { return _id; }
set { _id = value; }
}
public MyEnum? EnumValue
{
get { return _myEnum; }
set { _myEnum = value; }
}
public MyClass(string id)
{
this._id = id;
}
public MyClass() : this("")
{
}
}
Yes, but you can't do it anymore with SerializableAttribute I think.
You should implement ISerializable and provide your own serializer/deserializer. You can use the default serializer (new BinaryFormatter().serializer() e.g), but you have to implement a custom deserialization.
Related
I always thought that property is something like shortcut for methods. However this example makes me strange. It seems to me that functions changePropertyId and changeMethodId do the same. However reality is different. Only second one works properly. Can somebody can explain it?
class Program
{
static void Main(string[] args)
{
User user = new User();
user.changePropertyId(1);
Console.Write(user.Id);
user.changeMethodId(1);
Console.Write(user.Id);
Console.ReadLine();
}
}
public class DBObject
{
private int mId;
public int Id { set { mId = Id; } get { return mId; } }
public void setId(int aId)
{mId = aId;}
}
public class User : DBObject
{
public void changePropertyId(int aId) { Id = aId; }
public void changeMethodId(int aId) { setId(aId); }
}
The result from first function is 0, from second is 1. My intention was to get 1 from both.
You have a bug here:
set { mId = Id; }
This should read:
set { mId = value; }
The value is the new value which you should use in a property
setter. Due to this bug basically your setter has no effect.
Here is the fixed version.
public class DBObject
{
private int mId;
public int Id { set { mId = value; } get { return mId; } }
public void setId(int aId) { mId = aId; }
}
Basically they should do the same in your sample. However, there is a little mistake in the property's implementation that you need to correct to make it work:
public int Id { set { mId = value; } get { return mId; } }
value is a reserved name for the parameter of the property setter that contains the new value that should be assigned to the property.
This line is wrong:
public int Id { set { mId = Id; } get { return mId; } }
You're assigning the current property value to the backing field in the setter so you're not actually changing the value. That should read:
public int Id { set { mId = value; } get { return mId; } }
That said, if you're not going to add any code to the getter or setter other than that to return the backing field and set the backing field then you should do away with the backing field altogether and just do this:
public int Id { get; set; }
Note there that I have put the getter before the setter, which is a universal convention and something that you should do too.
Your setter is Invalid: it should be mId = value;. value is a special variable used in setter which contains the value to set.
I need a little help i am using a class and want to set the properties based on choice on type int,string and datetime here is my code that i wrote but as my constructor will be confused between public string paramValue and public int? paramValue what is the best way to set properties based on choice so only one property can be set a time.Thanks for any suggestion
public class PassData
{
private string _ParamName { get; set; }
private int? _ParamValueInt { get; set; }
private string _ParamValueString { get; set; }
private DateTime? _ParamValueDateTime { get; set; }
public string paramName
{
get { return _ParamName; }
set { _ParamName = value;}
}
public string paramValue
{
get { return _ParamValueString; }
set {_ParamValueString = value; }
}
public int? paramValue
{
get { return _ParamValueInt; }
set { _ParamValueInt = value; }
}
public PassData(string ParamName, int ParamValue)
{
paramName = ParamName;
paramValue = ParamValue;
}
public PassData(string ParamName, string ParamValue)
{
ParamName = ParamName;
ParamValueString = ParamValue;
}
public PassData(string ParamName, DateTime ParamValue)
{
ParamName = ParamName;
ParamValueDateTime = ParamValue;
}
}
Basically, you can't have multiple properties on an object that only differ by type. You have a few options.
1) Create a single property that can hold various types:
private Object _paramValue;
public Object ParamValue
{
get { return _paramValue; }
set {_paramValue= value; }
}
In your setter, you can throw an exception if the value is a type you don't like. You'd also have to upcast the result every time you called the getter, making this solution not ideal. If you want to go this route, I'd suggest making the property an interface, and defining various implementations for the types of data you need.
2) Create a generic class:
public class PassData<T>
{
private T _paramValue;
public T paramValue
{
get { return _paramValue; }
set {_paramValue= value; }
}
}
This has the disadvantage of not being able to change the type after the instance is created. It was unclear if this was a requirement for you.
I like this design as it provides for the possibility of making the constructor for this class private:
public class PassData<T>
{
private PassData(T value)
{
this._paramValue = value;
}
}
If you did this, you can create overloaded static methods to allow the creation of instances:
public static PassData<String> CreateValue(string value)
{
return new PassData<String>(value);
}
public static PassData<Int32> CreateValue(Int32 value)
{
return new PassData<Int32>(value);
}
That way, you can control what types can be created.
Not an answer (in the sense that it does not offer you a way to do what you're trying to do, as Mike Christensen's answer covers it). I just wanted to get more into why what you are trying to do is not working.
Your expectation for it to work is not unreasonable per se, the issue is that c# is not polymorphic on return values. I think some other languages are, C# is not.
i.e. while in c#, you can do:
public void test(int val) {}
public void test(string val) {}
// When you call `test` with either an int or a string,
// the compiler will know which one to call
you CAN'T do:
public int test() {return 1;}
public string test() {return "1";}
// does not compile. The compiler should look at the call
// site and see what you assign the result of "test()" to
// to decide. But there are various edge cases and it was decided
// to leave this out of the language
Now, the get on string paramValue is functionally equivalent to this scenario. You're trying to get the compiler to decide which paramValue to call based on the return value.
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().
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;
}
I've run into a really interesting runtime bug which generates a rogue stack overflow.
I've defined a structure as follows:
public enum EnumDataType { Raspberry, Orange, Pear, Apple };
public class DataRequest
{
public long DataSize
{
get { return 0; }
set { DataSize = value; }
}
public EnumDataType DataType
{
get { return EnumDataType.Apple; }
set { DataType = value; }
}
}
The following lines work perfectly:
DataRequest request = new DataRequest();
request.DataSize = 60;
However, when I step over the following line in code, it generates a stack overflow:
request.DataType = EnumDataType.Raspberry;
Of course, I can fix it by removing the defaults, or using auto get/set, but I need it to be both readable and writable, and return a default - any ideas?
public long DataSize { get { return 0; } set { DataSize = value; } }
You are constantly setting the value of DataSize. You need to create a local variable and use that instead. e.g.
private long dataSize;
public long DataSize
{
get { return this.dataSize; }
set { this.dataSize = value; }
}
EDIT
I've written DataSize but the same applies to DataType
As others have said, the stack overflow occurs because your property setter is just calling itself. It may be simpler to understand if you think of it as a method:
// This obviously recurses until it blows up
public void SetDataType(long value)
{
SetDataType(value);
}
As I understand it, you're trying to create normal properties but with a default value, right?
In that case, you need backing variables which are set by the setters - and the getters should return those variables, too. It's the variables which should get default values:
private long dataSize = 0;
public long DataSize {
get { return dataSize; }
set { dataSize = value; }
}
private EnumDataType dataType = EnumDataType.Apple;
public EnumDataType DataType {
get { return dataType; }
set { dataType = value; }
}
Alternatively, use automatic properties but set the defaults in your constructor:
public long DataSize { get; set; }
public EnumDataType DataType { get; set; }
public DataRequest()
{
DataSize = 0; // Not really required; default anyway
DataType = EnumDataType.Apple;
}
stack overflow happens because in the setter you are setting the property to a value (Ie you are trying to get something to set itself to something ... which causes an infinite loop) ... which means that it tries to set itself to a value which means its tries to set itself to a value untill boom
your properties will never get the values you are setting because they always return the same value (not the stored value)
public enum EnumDataType { Raspberry, Orange, Pear, Apple };
public class DataRequest
{
private long _dataSize = 0;
private EnumDataType _dataType = EnumDataType.Apple;
public long DataSize { get { return _dataSize ; } set { _dataSixe= value; } }
public EnumDataType DataType { get { return _dataType; } set { _dataType= value; } }
}
is what you really wanted
you have to implemet it with a backing store:
private EnumDataType dataType;
public EnumDataType DataType { get { return EnumDataType.Apple; } set { dataType = value; } }
}
You should do so anytime you do some acion in the getter and setters. By the way, why can you even set the variables? you can't read them out, you always get EnumDataType.Apple. If you want a start value, you can do like this:
private EnumDataType dataType = EnumDataType.Apple;
public EnumDataType
{
get
{
return dataType;
}
set
{
dataType = value;
}
}
I don't understand how the first line:
request.DataSize = 60;
Doesn't cause a stack overflow - my advice would be to use backing properties:
public class DataRequest
{
protected int dataSize = 0;
protected EnumDataType enumDataType;
public long DataSize { get { return 0; } set { dataSize = value; } }
public EnumDataType DataType { get { return EnumDataType.Apple; } set { enumDataType = value;}
}