How to serialize Nullable<bool>? - c#

I want to serialize a nullable bool simply by converting it to a string
public static string SerializeNullableBoolean(bool? b)
{
if (b == null)
{
return "null or -1 or .."; // What to return here?
}
else
{
return b.ToString();
}
}
What is the most appropriate string to serialize the null-value as?

Since bool.ToString() returns "True" or "False", I would go with "Null". I would also rewrite this as:
return b.HasValue ? b.ToString() : "Null";
Edit: I take that back. bool?.ToString() returns empty string, so I would decide based on what's more convenient. If a person needs to read the output then "Null" is a better choice; if it only needs to be used in code then empty string is fine. If you go with empty string it is as simple as:
return b.ToString();

Why not:
b.ToString()
If b is null, then it returns an empty string. Since that's what the framework returns, I would use it to be consistent. This is also what XmlSerializer uses for nullable scalars.

If you're returning True/False for real bool values, you should return Null for symmetry's sake in case b is null.

Be consistent.
b.ToString()
returns the strings 'true' or 'false'. Thus if you return -1 it will be less consistent if you actually read the serialized files. The deserialization code will also become more "ugly" and less readable.
I would choose to serialize it to either the string 'unset' (or something along those lines) or the string 'null'. Unless you have really strict space requirements or really huge datasets to serialize the extra characters shouldn't really matter.

I would choose an empty string to represent the null-value.

If you are using the built in XmlSerializer you can also do the following to serialize the value (and prevent a lot of ugly custom serialization code):
[Serializable]
public class Foo
{
[XmlIgnore]
public bool? Bar { get; set; }
[XmlAttribute("Bar")]
[EditorBrowsable(EditorBrowsableState.Never)]
public string xmlBar
{
get { return Bar.ToString(); }
set
{
if (string.IsNullOrEmpty(value)) Bar = null;
else Bar = bool.Parse(value);
}
}
}

Personally I wouldn't use any of the above but simply use ShouldSerialize interface.
For example,
[XmlElement("SomeBoolean ", Namespace = "SomeNamespace")]
public bool? SomeBoolean { get; set; }
public bool ShouldSerializeSomeBoolean() { return SomeBoolean.HasValue; }

Related

Is there an easy way of getting all of an objects properties as a string?

I have a class called ReportToDownload that contains several properties. In the Assert part of a test I'm comparing expected and actual lists of ReportToDownload using an equality comparer I have written. For any items that don't match I was hoping to print out the contents of the expected and actual items as part of the message using:
actual[i].ToString()
but this just returns the name of the object - ReportToDownload. Is there any way of easily getting the whole contents of the object as a string?
Depending on who this is being shown to, a simple "no effort" solution is to use JSON:
Install-Package Newtonsoft.Json
Then...
JsonConvert.SerializeObject(actual[i])
Rather than using an equality comparison, write a method that compares every individual property using your unit test's framework built-in assertion methods, e.g.:
public void AssertEquals(ReportToDownload actual, ReportToDownload expected)
{
Assert.That(actual.PropertyA, Is.EqualTo(expected.PropertyA));
Assert.That(actual.PropertyB, Is.EqualTo(expected.PropertyB));
}
The built-in assertion methods will print the expected and actual values appropriately when there is a comparison failure.
Most likely, your unit test framework will also allow you to write your own assertions that will print the differences in a custom way, if necessary.
I don't know how useful this could be, but here's my take:
public class ClassA
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
public override string ToString()
{
string ret = string.Empty;
foreach (PropertyInfo pi in this.GetType().GetProperties())
{
ret += string.Format("{0}: {1}\r\n", pi.Name, pi.GetValue(this, null).ToString());
}
return ret;
}
}
Used like this:
ClassA a = new ClassA();
a.Prop1 = "Hello";
a.Prop2 = "World";
var toStringOutput = a.ToString();
You may have to handle more complex property types, but for basic ones, that should work.

Using code contracts in one property to provide hints about another property

I have a struct like this (simplified for brevity):
public struct Period
{
public DateTime? Start { get; private set; }
public DateTime? End { get; private set; }
public bool IsMoment
{
get { return this.Start.HasValue && this.Start == this.End; }
}
public Period(DateTime? start, DateTime? end) : this()
{
this.Start = start;
this.End = end;
}
public override string ToString()
{
return this.IsMoment
? this.Start.Value.ToString("g")
: string.Format("{0:g} – {1:g}", this.Start, this.End);
}
}
Everything works fine, but ReSharper is showing a warning on this.Start.Value.ToString:
Possible 'System.InvalidOperationException'
If I copy the body of the IsMoment property into the condition, the warning goes away, but I'd like to be able to reuse the property. I can disable the ReSharper warning with a comment (which is what I have done for the moment), or by changing ToString to string.Format, but I have a handful of other places like this in my code and it got me thinking. I'd try to resolve this using code contracts, but unfortunately I don't have a whole lot of experience with code contracts and I'm not sure how it would look.
Is there anyway I use code contracts to indicate to ReSharper that if IsMoment is true, then Start is not null?
Do something like this in IsMoment:
contract.ensures(result == false || start <> null);
(That's not exactly right. I'm typing this on my phone.)
UPDATE:
The problem could be due to the possibility of multithreaded code changing the value of Start between the IsMoment test and the Start.Value evaluation.
It may be more correct to copy the value into a local variable that cannot be modified by other threads.
public override string ToString()
{
Period local = this;
return local.IsMoment
? local.Start.Value.ToString("g")
: string.Format("{0:g} – {1:g}", local.Start, local.End);
}
This looks like some unnecessary work, and it may look inefficient, but it more "correct". If your struct is small, though, this may actually be more efficient in many cases.
Have tried wrapping parens around it?
public override string ToString()
{
return (this.IsMoment
? this.Start.Value.ToString("g")
: string.Format("{0:g} – {1:g}", this.Start, this.End));
}
This might be a case for using Contract.Assume.
public override string ToString()
{
if (this.IsMoment) {
Contract.Assume(this.Start.HasValue);
return this.Start.Value.ToString("g");
}
else
return string.Format("{0:g} – {1:g}", this.Start, this.End));
}

How to use multi properties in class that contain one variable?

I have class named "config" that have private string variable named "param".
I need to get from "config" class "param" variable sometimes as int type sometimes as bool type or string.
As I understand I need create 3 properties in config class,each property have to convert type, as follow:
The first property converts string to int, the second converts string to bool, the third property gets me the string value.
The class should look something like this:
class Config
{
private string param;
public int ParamAsInt
{
get
{
return int.Parse(param);
}
}
public bool ParamAsBool
{
get
{
return bool.Parse(param);
}
}
public string ParamAsString
{
get
{
return param;
}
}
}
But I don't know how can those properties be used in accordance to the variable type that I want to get out of class.
This code won't compile - int and such are reserved keywords and cannot be used as identifiers. You can either try naming your properties something like Int32Value, StringValue, etc., or try this:
public static implicit operator bool (Config config)
{
return bool.Parse(config.param);
}
public static implicit operator int (Config config)
{
return int.Parse(config.param);
}
This will allow for much cleaner code:
Config c = GetConfig("foo");
var isFeatureEnabled = false || c;
var spacing = 23 + GetConfig("bar");
You forgot to give your properties names. How would you expect to reference them? Something like this:
class Config
{
private string param;
public int ParamAsInt
{
get
{
return int.Parse(param);
}
}
public bool ParamAsBool
{
get
{
return bool.Parse(param);
}
}
public string ParamAsString
{
get
{
return param;
}
}
}
Note that I also fixed the casing in your calls to .Parse(). C# is case-sensitive. I also replaced the call to bool.TryParse() with bool.Parse(). The former (when used correctly, which this wasn't because it was missing a parameter) will only tell you if it is a bool, it won't tell you what value the bool actually has. (For example, bool.TryParse('false' out someBool) will return true.)
Of course, this code is a bit dangerous. You'll want to start with some more defensive programming to check those values. Basically, look up TryParse() and how to use it correctly. Something like this, for example:
public int ParamAsInt
{
get
{
var tmp = default(int);
if (int.TryParse(param, out tmp))
return tmp;
else
// do something else? throw a specific exception?
}
}
Additionally, what is the purpose of this code? It seems like a very rushed and poor design. For any given value of param (how is that even being set, by the way?) this just sort of randomly tries to expose typed properties for it. If you guess the correct one, you're still left with others that will throw exceptions. Surely there's a much cleaner way to accomplish what you're trying to do. So what are you trying to do?

How to implement C# enum for enumerated char(1) database field?

OK, so I have a database field of type char(1) that has a small number of possible state codes (e.g. 'F'= Failure, 'U'=Unknown, etc.). I'd like to have a C# enum class that corresponds to these states. I can do:
public enum StatusCode : byte {
Unknown = (byte) 'U',
Failure = (byte) 'F',
// etc.
}
So far so good. But in the DataTable returned from the database, the column values are System.Data.SqlTypes.SqlString instances. There are obviously some issues converting from a C# string (or even a C# char) to a C# byte (since C# char is really a UTF-16 codepoint). But in this case I know the values are constrained to a small set, and the code should throw an exception if a value outside this set comes through.
With that in mind, what's the best way of doing this? Is it safe to cast from a SqlString to a byte? Would Convert.ToByte() be better? Would it be better to simply use a switch/case construct to crosswalk the values into the enum?
I'm looking for the "best" way to do this, not only in terms of getting the right results but also for code clarity. I suppose I could also just use some constants like
public const char UnknownStatus = 'U';
public const char FailureStatus = 'F';
But I'd rather use an enum if possible. Any thoughts?
Edit: To clarify what I want do do with this, I'm expecting to use these values frequently throughout my code. For example, I want to be able to do things like:
public void DoSomething(StatusCode currentStatus) {
if(currentStatus == StatusCode.Failure) {
throw new SomeException();
}
switch(currentStatus) {
case StatusCode.Unknown:
// do something
break;
}
}
And so forth. I particularly want to avoid things like:
public void DoSomething(char currentStatus) {
if(currentStatus == 'F') {
// do something
}
}
Since in this case I'm using what amounts to "magic numbers" all over the place. In particular, this would make migrating to some other state-flagging system virtually impossible. Does that make sense?
Maybe a "constant" object?
public sealed class StatusCode {
private char value;
public static readonly StatusCode Unknown = new StatusCode('U');
public static readonly StatusCode Failure = new StatusCode('F');
private StatusCode(char v) {
value = v;
}
public override string ToString() {
return value.ToString();
}
}
Then, later in your code, you could use it like an enum: StatusCode.Unknown. You could also provide an internal method to 'parse' a received value into an object of StatusCode.
Skip to edit Have you tried this (which doesn't work as you've checked and commented):
public enum StatusCode : char
{
Failure = 'F',
Unknown = 'U',
...
}
EDIT - correct solution
or this (maybe even try with a struct):
public sealed class StatusCode
{
public static readonly char Failure = 'F';
public static readonly char Unknown = 'U';
...
public char Value { get; set; }
}
your code you provided would work like this:
public void DoSomething(StatusCode currentStatus) {
if(currentStatus.Value == StatusCode.Failure) {
throw new SomeException();
}
switch(currentStatus.Value) {
case StatusCode.Unknown:
// do something
break;
}
}
If you don't like to use Value property you can always implement implicit equality operator between StatusCode and char types. In that case, your code wouldn't change a bit.
If you're on .NET 2.0 and higher, you could implement this using a generic dictionary:
Dictionary<char,string> statusCode = new Dictionary<char,string>();
statusCode.Add('U', "Unknown");
statusCode.Add('F', "Failure");
or alternatively:
Dictionary<char,StatusCode> statusCode = new Dictionary<char,StatusCode>();
statusCode.Add('U', StatusCode.Unknown);
statusCode.Add('F', StatusCode.Failure);
and you could access the string representation for a given code like so:
string value = statusCode['A'];
or
StatusCode myCode = statusCode['A'];
and so on. You would have to fill that dictionary from the database values, or from some kind of a config file or something.
Marc
Would something like this work for you?
public Enum StatusCode : int{
[StringValue("U")]
Unknown =0,
[StringValue["F"]
Failuer=1
}
If you have a table called StatusCode which includes an integer primary key then you could use that as your identifier as well as hook it into your logic. And in that case, the enum would be the best thing to use. Though i'm not sure if this is feasible for you.
One option is to setup your enum with identical names to the values in your database, such as:
enum StatusCode
{
/// <summary>Unknown</summary>
U = 0,
/// <summary>Failure</summary>
F,
/// <summary>Etc</summary>
E
}
Then use a static method to convert char values to an enumerated value
private StatusCode CharToEnum(string statusCodeChar)
{
foreach (FieldInfo fi in typeof(StatusCode).GetFields())
{
if (fi.Name == statusCodeChar) return (StatusCode)fi.GetValue(null);
}
return StatusCode.U;
}
Short and sweet my man.. Does everything you need it to. You shouldn't need to use enum because you don't need it to assign an internal value to your possible states, you already know the values to your states.
public sealed class StatusCode
{
public const string Unknown= "U";
public const string Failure= "F";
public const string Success= "S";
}

How can I get XmlSerializer to encode bools as yes/no?

I'm sending xml to another program, which expects boolean flags as "yes" or "no", rather than "true" or "false".
I have a class defined like:
[XmlRoot()]
public class Foo {
public bool Bar { get; set; }
}
When I serialize it, my output looks like this:
<Foo><Bar>true</Bar></Foo>
But I would like it to be this:
<Foo><Bar>yes</Bar></Foo>
Can I do this at the time of serialization? I would prefer not to have to resort to this:
[XmlRoot()]
public class Foo {
[XmlIgnore()]
public bool Bar { get; set; }
[XmlElement("Bar")]
public string BarXml { get { return (Bar) ? "yes" : "no"; } }
}
Note that I also want to be able to deserialize this data back again.
Ok, I've been looking into this some more. Here's what I've come up with:
// use this instead of a bool, and it will serialize to "yes" or "no"
// minimal example, not very robust
public struct YesNo : IXmlSerializable {
// we're just wrapping a bool
private bool Value;
// allow implicit casts to/from bool
public static implicit operator bool(YesNo yn) {
return yn.Value;
}
public static implicit operator YesNo(bool b) {
return new YesNo() {Value = b};
}
// implement IXmlSerializable
public XmlSchema GetSchema() { return null; }
public void ReadXml(XmlReader reader) {
Value = (reader.ReadElementContentAsString() == "yes");
}
public void WriteXml(XmlWriter writer) {
writer.WriteString((Value) ? "yes" : "no");
}
}
Then I change my Foo class to this:
[XmlRoot()]
public class Foo {
public YesNo Bar { get; set; }
}
Note that because YesNo is implicitly castable to bool (and vice versa), you can still do this:
Foo foo = new Foo() { Bar = true; };
if ( foo.Bar ) {
// ... etc
In other words, you can treat it like a bool.
And w00t! It serializes to this:
<Foo><Bar>yes</Bar></Foo>
It also deserializes correctly.
There is probably some way to get my XmlSerializer to automatically cast any bools it encounters to YesNos as it goes - but I haven't found it yet. Anyone?
Very simple. Use a surrogate property. Apply XmlIgnore on the actual property. The surrogate is a string, and must use the XmlElement attribute that takes a element-name override. Specify the name of the actual property in the override. The surrogate property serializes differently based on the value of the actual property. You must also provide a setter for the Surrogate, and the setter should set the actual property appropriately, for whatever value it serialized. In other words it needs to go both ways.
Snip:
public class SomeType
{
[XmlElement]
public int IntValue;
[XmlIgnore]
public bool Value;
[XmlElement("Value")]
public string Value_Surrogate {
get { return (Value)? "Yes, definitely!":"Absolutely NOT!"; }
set { Value= (value=="Yes, definitely!"); }
}
}
click here for full compilable source example.
Making a bool value serialize as "yes" or "no" changes the data type from being a boolean at all. Instead, can you add a separate property which evaluates a boolean and returns "yes" or "no" as appropriate for it's data type? Maybe you could even force "yes" or "no" by making the return type be an enum which only specifies those values.
public YesOrNo DoYouLoveIt
{
get { return boolToEvaluate ? YesOrNo.Yes : YesOrNo.No; }
}
That might be overkill, but might answer your need. The only reason I bring up an enum for such a simple value is you'd be restricting the values vs. allowing any string.
I use the property method, but instead of checking to see if the string is equal to yes or no, I prefer to check if the string starts with (case insensitive) "YT1". This allows the file to contain true, True, t, T, y, Y, yes, Yes, 1, etc. all which will evaluate to true. While I can specify that false is false, False, f, F, n, N, no, No, 0, etc., anything that doesn't match the true still evaluates to false.
Your property example is probably the simplest way you could do it. If it helps, I believe you don't need to make it a public property, since the attribute implements ISerializable on the class behind your back. To enable deserialization, you should be able to just implement set { Bar = value == "yes"; }
#Blorgbeard:
If you have more then one of these YesNo classes in an object class,
make sure to read the entire element.
public void ReadXml(XmlReader reader)
{
string element = reader.ReadOuterXml();
int startIndex = element.IndexOf('>') + 1;
int length = element.LastIndexOf('<') - startIndex;
string text = (element.Substring(startIndex, length).ToLowerInvariant();
Value = (text == "yes");
}
Otherwise this might cause problems.
The ReadXml method must reconstitute your object using the information that was written by the WriteXml method.
When this method is called, the reader is positioned at the start of the element that wraps the information for your type. That is, just
before the start tag that indicates the beginning of a serialized
object. When this method returns, it must have read the entire element
from beginning to end, including all of its contents. Unlike the
WriteXml method, the framework does not handle the wrapper element
automatically. Your implementation must do so. Failing to observe
these positioning rules may cause code to generate unexpected runtime
exceptions or corrupt data.
What you're needing to do sounds more like a display issue. If your application allows, you will be better off keeping the data type as a boolean and displaying Yes/No in your user interface.

Categories