I have the following ugly code:
if (msg == null ||
msg.Content == null ||
msg.Content.AccountMarketMessage == null ||
msg.Content.AccountMarketMessage.Account == null ||
msg.Content.AccountMarketMessage.Account.sObject == null) return;
Is there a way to chain check for null values in C#, so that I don't have to check each individual level?
One of the proposals in C# 6 would be to add a new Null Propogation operator.
This will (hopefully) allow you to write:
var obj = msg?.Content?.AccountMarketMessage?.Account?.sObject;
if (obj == null) return;
Unfortunately, there is nothing in the language at this point that handles this.
There is not currently such a thing, but it may be coming to .NET very soon. There is a well-known User Voice thread on the subject. And as noted in this article, the Visual Studio team has recently announced that:
We are seriously considering this feature for C# and VB, and will be
prototyping it in coming months.
Edit: and as noted in Reed Copsey's answer above, it is now a planned addition for C# 6. There are better details on the Codeplex pages he linked.
There is no built-in support for this, but you can use an extension method for that:
public static bool IsNull<T>(this T source, string path)
{
var props = path.Split('.');
var type = source.GetType();
var currentObject = type.GetProperty(props[0]).GetValue(source);
if (currentObject == null) return true;
foreach (var prop in props.Skip(1))
{
currentObject = currentObject.GetType()
.GetProperty(prop)
.GetValue(currentObject);
if (currentObject == null) return true;
}
return false;
}
Then call it:
if ( !msg.IsNull("Content.AccountMarketMessage.Account.sObject") ) return;
You need monads and Monadic null checking. Could have a look at Monads.Net package. It can help with simplifying null tests and getting values from deep navigation properties
Something like
var sObject = person.With(p=>p.Content).With(w=>w.AccountMarketMessage ).With(p=>p.Account).With(p=>p.Object);
If you wanted a default value then
var sObject = person.With(p=>p.Content).With(w=>w.AccountMarketMessage).With(p=>p.Account).Return(p=>p.Object, "default value");
You can lazily evaluate the values using lambda expressions. This is overkill for a simple null check, but can be useful for chaining more complex expressions in a "fluent" manner.
Example
// a type that has many descendents
var nested = new Nested();
// setup an evaluation chain
var isNull =
NullCheck.Check( () => nested )
.ThenCheck( () => nested.Child )
.ThenCheck( () => nested.Child.Child )
.ThenCheck( () => nested.Child.Child.Child )
.ThenCheck( () => nested.Child.Child.Child.Child );
// handle the results
Console.WriteLine( isNull.IsNull ? "null" : "not null" );
Code
This is a full example (albeit draft-quality code) that can be pasted into a console app or LINQPad.
public class Nested
{
public Nested Child
{
get;
set;
}
}
public class NullCheck
{
public bool IsNull { get; private set; }
// continues the chain
public NullCheck ThenCheck( Func<object> test )
{
if( !IsNull )
{
// only evaluate if the last state was "not null"
this.IsNull = test() == null;
}
return this;
}
// starts the chain (convenience method to avoid explicit instantiation)
public static NullCheck Check( Func<object> test )
{
return new NullCheck { IsNull = test() == null };
}
}
private void Main()
{
// test 1
var nested = new Nested();
var isNull =
NullCheck.Check( () => nested )
.ThenCheck( () => nested.Child )
.ThenCheck( () => nested.Child.Child )
.ThenCheck( () => nested.Child.Child.Child )
.ThenCheck( () => nested.Child.Child.Child.Child );
Console.WriteLine( isNull.IsNull ? "null" : "not null" );
// test 2
nested = new Nested { Child = new Nested() };
isNull = NullCheck.Check( () => nested ).ThenCheck( () => nested.Child );
Console.WriteLine( isNull.IsNull ? "null" : "not null" );
// test 3
nested = new Nested { Child = new Nested() };
isNull = NullCheck.Check( () => nested ).ThenCheck( () => nested.Child ).ThenCheck( () => nested.Child.Child );
Console.WriteLine( isNull.IsNull ? "null" : "not null" );
}
Again: you probably shouldn't use this in lieu of simple null checks due to the complexity it introduces, but it's an interesting pattern.
.NET Fiddle
As stated there is a plan to have c# 6.0 implement the ? operator to facilitate this process somewhat. If you cannot wait, I would suggest using a lambda expression and a simple helper function to solve this.
public E NestedProperty<T,E>(T Parent, Func<T,E> Path, E IfNullOrEmpty = default(E))
{
try
{
return Path(Parent);
}
catch
{
return IfNullOrEmpty;
}
}
This could be used int value = NestedProperty<First,int>(blank,f => f.Second.Third.id); as shown in the demo below
program
public class Program
{
public void Main()
{
First blank = new First();
First populated = new First(true);
//where a value exists
int value = NestedProperty<First,int>(blank,f => f.Second.Third.id);
Console.WriteLine(value);//0
//where no value exists
value = NestedProperty<First,int>(populated,f => f.Second.Third.id);
Console.WriteLine(value);//1
//where no value exists and a default was used
value = NestedProperty<First,int>(blank,f => f.Second.Third.id,-1);
Console.WriteLine(value);//-1
}
public E NestedProperty<T,E>(T Parent, Func<T,E> Path, E IfNullOrEmpty = default(E))
{
try
{
return Path(Parent);
}
catch
{
return IfNullOrEmpty;
}
}
}
simple demo structure
public class First
{
public Second Second { get; set; }
public int id { get; set; }
public First(){}
public First(bool init)
{
this.id = 1;
this.Second = new Second();
}
}
public class Second
{
public Third Third { get; set; }
public int id { get; set; }
public Second()
{
this.id = 1;
this.Third = new Third();
}
}
public class Third
{
public int id { get; set; }
public Third()
{
this.id = 1;
}
}
Since 3.5 (maybe earlier), You could write very simple extension method
public static TResult DefaultOrValue<T, TResult> (this T source,
Func<T, TResult> property) where T : class
{
return source == null ? default(TResult) : property(source);
}
You may name this method even shortier and then use like this
var instance = new First {SecondInstance = new Second
{ThirdInstance = new Third {Value = 5}}};
var val =
instance .DefaultOrValue(x => x.SecondInstance)
.DefaultOrValue(x => x.ThirdInstance)
.DefaultOrValue(x => x.Value);
Console.WriteLine(val);
Console.ReadLine();
so source classes are:
public class Third
{
public int Value;
}
public class First
{
public Second SecondInstance;
}
public class Second
{
public Third ThirdInstance;
}
Related
I'm using Indexers in my class to make searching through a list easier. However, I want to be able to return both a bool and an int. Not at the same time but determine whether it's a bool or an int and then return it.
public class uPermissions
{
private List<uPermission> permissions = new List<uPermission> ()
{
new uPermission ("canBuild", false),
new uPermission ("canClaim", false),
new uPermission ("canUnClaim", false),
new uPermission ("canInvite", false),
new uPermission ("canKick", false),
new uPermission ("canSetHome", false)
};
private List<uConstraint> constraints = new List<uConstraint> ();
public bool this[string index]
{
get
{
return permissions.Where (p => p.name == index).First ().allowed;
}
set
{
permissions.Where (p => p.name == index).First ().allowed = value;
}
}
public int this[string index]
{
get
{
return constraints.Where (c => c.name == index).First ().count;
}
set
{
constraints.Where (c => c.name == index).First ().count = value;
}
}
public bool exists (string permission)
{
var perm = permissions.Where (p => p.name.ToLower () == permission.ToLower ()).First ();
return (perm != null) ? true : false;
}
public void setAllTrue ()
{
foreach (uPermission p in permissions)
{
p.allowed = true;
}
}
public void setAllFalse ()
{
foreach (uPermission p in permissions)
{
p.allowed = false;
}
}
}
public class uConstraint
{
public string name;
public int count;
public uConstraint () { }
public uConstraint (string name, int count)
{
this.name = name;
this.count = count;
}
}
public class uPermission
{
public string name;
public bool allowed;
public uPermission () { }
public uPermission (string name, bool allowed)
{
this.name = name;
this.allowed = allowed;
}
}
That's my code. I saw something about templates while searching but I don't understand how it works or if it's even the right solution. If anyone can give some insight it would be greatly appreciated
C# will not allow you to distinguish overloads purely based on their return types (they must differ in at least one parameter type or type argument count).
You can create a generic method and use the type argument to distinguish between your two intentions. E.g.
class uPermissions {
public T GetAllowedOrCount<T>(string index) {
get {
if (typeof(T) == typeof(bool) {
return permissions.Where (p => p.name == index).First ().allowed;
} else if (typeof(T) == typeof(int) {
return constraints.Where (c => c.name == index).First ().count;
}
throw new InvalidOperationException("only bool and int are supported");
}
}
and then you'd call it with an explicit type argument, such as
var fooCount = uPermissions.GetAllowedOrCount<int>("foo")
var fooAllowed = uPermissions.GetAllowedOrCount<string>("foo")
Note that this solution would not work with the this indexer as C# does not support generic indexers.
I suppose though we agree that this does not sound like something you'd want to do. Your dispatch is now run-time as opposed to compile-time and you would certainly not gain type safety as
uPermissions.GetAllowedOrCount<double>("foo")
would also compile and blow up with a runtime exception.
To be honest I also would find it very confusing that the same (or overloaded) method returns/sets two totally different things (i.e. allowed vs count). I'd rather have two different methods for that or return a data structure (that has a getter for allowed/count) from a single method. In the latter case you could also use indexers if that is what you fancy.
The overload resolution mechanism in C# doesn't regard return values. You can't have two methods with the same name and argument, differing only in their return type.
Indexer is just a method (or two), so it follows the same rules. You can't have two indexers with the same arguments, differing only in their return type.
I suggest to use two different properties each containing a dictionary or some List-type instead. That way you could write something like this:
bool foo = uPermissionsInstance.Permissions["someName"];
int bar = uPermissionsInstance.Constraints["someOtherName"];
Alternatively there's a "hack" you could use, that works quite well:
Write a Class that has two implicit casts implemented. One for int and one for bool.
Return this class instead of the int or bool and set its internal value appropriately.
That way you can write the following. But this won't work with the setter!
bool foo = uPermissionsInstance["someName"];
int bar = uPermissionsInstance["someOtherName"];
Implementation:
public IntBoolValue this[string index]
{
get
{
// Here you need to check whether you can find an entry in permissions or in constraints. Then return the found value.
return new IntBoolValue(permissions.Where (p => p.name == index).First ().allowed);
}
}
// ------------------
internal struct IntBoolValue
{
internal int internalInt;
internal bool internalBool;
public IntBoolValue(int value) { this.internalInt = value; }
public IntBoolValue(bool value) { this.internalBool = value; }
public static implicit operator bool(IntBoolValue value)
{
return value.internalBool;
}
public static implicit operator int(IntBoolValue value)
{
return value.internalInt;
}
}
Firstly I have seen IEqualityComparer for anonymous type and the answers there do not answer my question, for the obvious reason that I need an IEqualityComparer not and IComparer for use with Linq's Distinct() method. I have checked the other answers too and these fall short of a solution...
The Problem
I have some code to manipulate and pull records in from a DataTable
var glext = m_dtGLExt.AsEnumerable();
var cflist =
(from c in glext
orderby c.Field<string>(m_strpcCCType),
c.Field<string>(m_strpcCC),
c.Field<string>(m_strpcCCDesc),
c.Field<string>(m_strpcCostItem)
select new
{
CCType = c.Field<string>(m_strpcCCType),
CC = c.Field<string>(m_strpcCC),
CCDesc = c.Field<string>(m_strpcCCDesc),
CostItem = c.Field<string>(m_strpcCostItem)
}).Distinct();
but I need the distinct method to be case insensitive. What is throwing me here is the use of anonymous types.
Attempted Solution 1
If I had SomeClass which had concrete objects I could obviously do
public class SumObject
{
public string CCType { get; set; }
public string CC { get; set; }
public string CCDesc { get; set; }
public string CostItem { get; set; }
}
I could obviously do this
List<SumObject> lso = new List<SumObject>()
{
new SumObject() { CCType = "1-OCC", CC = "300401", CCDesc = "Rooney", CostItem = "I477" },
new SumObject() { CCType = "1-OCC", CC = "300401", CCDesc = "Zidane", CostItem = "I677" },
new SumObject() { CCType = "1-OCC", CC = "300401", CCDesc = "Falcao", CostItem = "I470" },
};
var e = lso.Distinct(new SumObjectComparer()); // Great :]
where
class SumObjectComparer : IEqualityComparer<SumObject>
{
public bool Equals(SumObject x, SumObject y)
{
if (Object.ReferenceEquals(x, y))
return true;
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
return x.CCType.CompareNoCase(y.CCType) == 0 &&
x.CC.CompareNoCase(y.CC) == 0 &&
x.CCDesc.CompareNoCase(y.CCDesc) == 0 &&
x.CostItem.CompareNoCase(y.CostItem) == 0;
}
public int GetHashCode(SumObject o)
{
if (Object.ReferenceEquals(o, null))
return 0;
int hashCCType = String.IsNullOrEmpty(o.CCType) ?
0 : o.CCType.ToLower().GetHashCode();
int hashCC = String.IsNullOrEmpty(o.CC) ?
0 : o.CC.ToLower().GetHashCode();
int hashCCDesc = String.IsNullOrEmpty(o.CCDesc) ?
0 : o.CCDesc.ToLower().GetHashCode();
int hashCostItem = String.IsNullOrEmpty(o.CostItem) ?
0 : o.CostItem.ToLower().GetHashCode();
return hashCCType ^ hashCC ^ hashCCDesc ^ hashCostItem;
}
}
However, the use of anonymous types in the above Linq query are throwing me.
Attempted Solution 2
To attempt another solution to this (and because I have the same issue elsewhere) I generated the following generic comparer class
public class GenericEqualityComparer<T> : IEqualityComparer<T>
{
Func<T, T, bool> compareFunction;
Func<T, int> hashFunction;
public GenericEqualityComparer(Func<T, T, bool> compareFunction, Func<T, int> hashFunction)
{
this.compareFunction = compareFunction;
this.hashFunction = hashFunction;
}
public bool Equals(T x, T y) { return compareFunction(x, y); }
public int GetHashCode(T obj) { return hashFunction(obj); }
}
so that I could attempt to do
var comparer = new GenericEqualityComparer<dynamic>(
(x, y) => { /* My equality stuff */ },
o => { /* My hash stuff */ });
but this casts the returned value as IEnumerable<dynamic> which in turn effects my forthcoming use of cflist, so that in a following query the join fails.
var cf =
(from o in cflist
join od in glext
on new { o.CCType, o.CC, o.CCDesc, o.CostItem } equals new
{
CCType = od.Field<string>(m_strpcCCType),
CC = od.Field<string>(m_strpcCC),
CCDesc = od.Field<string>(m_strpcCCDesc),
CostItem = od.Field<string>(m_strpcCostItem)
}
into c
select new { ... }
I don't want to get into ugly casting to and from IEnumerable<T>s due to the heavy use of this code...
Question
Is there a way I can create my an IEquailityComparer for my anonymous types?
Thanks for your time.
Is there a way I can create my an IEquailityComparer for my anonymous types?
Sure. You just need to use type inference. For example, you could have something like:
public static class InferredEqualityComparer
{
public static IEqualityComparer<T> Create<T>(
IEnumerable<T> example,
Func<T, T, bool> equalityCheck,
Func<T, int> hashCodeProvider)
{
return new EqualityComparerImpl<T>(equalityCheck, hashCodeProvider);
}
private sealed class EqualityComparerImpl<T> : IEqualityComparer<T>
{
// Implement in the obvious way, remembering the delegates and
// calling them appropriately.
}
}
Then:
var glext = m_dtGLExt.AsEnumerable();
var query = from c in glext
orderby ...
select new { ... };
var comparer = InferredEqualityComparer.Create(query,
(x, y) => { ... },
o => { ... }
);
var distinct = query.Distinct(comparer);
Basically the first parameter to the method is just used for type inference, so that the compiler can work out what type to use for the lambda expression parameters.
You could create the comparer ahead of time by creating a sample of the anonymous type:
var sample = new[] { new { ... } };
var comparer = InferredExqualityComparer.Create(sample, ...);
var distinct = (... query here ... ).Distinct(comparer);
but then any time you change the query you've got to change the sample too.
This post may get what you want. Although for .NET 2.0 it also works for newer versions (see the bottom of this post for how to achieve this). In contrast to Jon Skeets solution we won´t use a factory-method like create. But this is only syntactic sugar I think.
I have an object lets call it ObjectA
and that object has 10 properties and those are all strings.
var myObject = new {Property1="",Property2="",Property3="",Property4="",...}
is there anyway to check to see whether all these properties are null or empty?
So any built-in method that would return true or false?
If any single of them is not null or empty then the return would be false. If all of them are empty it should return true.
The idea is I do not want to write 10 if statement to control if those properties are empty or null.
Thanks
You can do it using Reflection
bool IsAnyNullOrEmpty(object myObject)
{
foreach(PropertyInfo pi in myObject.GetType().GetProperties())
{
if(pi.PropertyType == typeof(string))
{
string value = (string)pi.GetValue(myObject);
if(string.IsNullOrEmpty(value))
{
return true;
}
}
}
return false;
}
Matthew Watson suggested an alternative using LINQ:
return myObject.GetType().GetProperties()
.Where(pi => pi.PropertyType == typeof(string))
.Select(pi => (string)pi.GetValue(myObject))
.Any(value => string.IsNullOrEmpty(value));
I suppose you want to make sure that all properties are filled in.
A better option is probably by putting this validation in the constructor of your class and throw exceptions if validation fails. That way you cannot create a class that is invalid; catch exceptions and handle them accordingly.
Fluent validation is a nice framework (http://fluentvalidation.codeplex.com) for doing the validation. Example:
public class CustomerValidator: AbstractValidator<Customer>
{
public CustomerValidator()
{
RuleFor(customer => customer.Property1).NotNull();
RuleFor(customer => customer.Property2).NotNull();
RuleFor(customer => customer.Property3).NotNull();
}
}
public class Customer
{
public Customer(string property1, string property2, string property3)
{
Property1 = property1;
Property2 = property2;
Property3 = property3;
new CustomerValidator().ValidateAndThrow();
}
public string Property1 {get; set;}
public string Property2 {get; set;}
public string Property3 {get; set;}
}
Usage:
try
{
var customer = new Customer("string1", "string", null);
// logic here
} catch (ValidationException ex)
{
// A validation error occured
}
PS - Using reflection for this kind of thing just makes your code harder to read. Using validation as shown above makes it explicitly clear what your rules are; and you can easily extend them with other rules.
The following code returns if any property is not null.
return myObject.GetType()
.GetProperties() //get all properties on object
.Select(pi => pi.GetValue(myObject)) //get value for the property
.Any(value => value != null); // Check if one of the values is not null, if so it returns true.
Here you go
var instOfA = new ObjectA();
bool isAnyPropEmpty = instOfA.GetType().GetProperties()
.Where(p => p.GetValue(instOfA) is string) // selecting only string props
.Any(p => string.IsNullOrWhiteSpace((p.GetValue(instOfA) as string)));
and here's the class
class ObjectA
{
public string A { get; set; }
public string B { get; set; }
}
A slightly different way of expressing the linq to see if all string properties of an object are non null and non empty:
public static bool AllStringPropertyValuesAreNonEmpty(object myObject)
{
var allStringPropertyValues =
from property in myObject.GetType().GetProperties()
where property.PropertyType == typeof(string) && property.CanRead
select (string) property.GetValue(myObject);
return allStringPropertyValues.All(value => !string.IsNullOrEmpty(value));
}
Note if you've got a data structural hierarchy and you want to test everything in that hierarchy, then you can use a recursive method. Here's a quick example:
static bool AnyNullOrEmpty(object obj) {
return obj == null
|| obj.ToString() == ""
|| obj.GetType().GetProperties().Any(prop => AnyNullOrEmpty(prop.GetValue(obj)));
}
To only check if all properties are null:
bool allPropertiesNull = !myObject.GetType().GetProperties().Any(prop => prop == null);
you can use reflection and extension methods to do this.
using System.Reflection;
public static class ExtensionMethods
{
public static bool StringPropertiesEmpty(this object value)
{
foreach (PropertyInfo objProp in value.GetType().GetProperties())
{
if (objProp.CanRead)
{
object val = objProp.GetValue(value, null);
if (val.GetType() == typeof(string))
{
if (val == "" || val == null)
{
return true;
}
}
}
}
return false;
}
}
then use it on any object with string properties
test obj = new test();
if (obj.StringPropertiesEmpty() == true)
{
// some of these string properties are empty or null
}
No, I don't think there is a method to do exactly that.
You'd be best writing a simple method that takes your object and returns true or false.
Alternatively, if the properties are all the same, and you just want to parse through them and find a single null or empty, perhaps some sort of collection of strings would work for you?
You can try the following query :
if the object is "referenceKey" (where few properties may be null )
referenceKey.GetType().GetProperties().Where(x => x.GetValue(referenceKey) == null)
I need to count the properties where the value is set to not Null, so I have used the following query :
var countProvidedReferenceKeys = referenceKey.GetType().GetProperties().Where(x => x.GetValue(referenceKey) != null).Count();
I have a class what takes care of reading and holding the XML file.
Right now a simple version of it looks like this:
public class EstEIDPersoConfig
{
public bool LaunchDebugger { get ; set; }
public string Password { get; set; }
public int Slot { get; set; }
public string Reader { get; set; }
public string TestInput { get; set; }
public bool Logging { get; set; }
public EstEIDPersoConfig()
{
XElement xml = XElement.Load(myxml.xml);
XElement Configuration = xml.Element("Configuration");
LaunchDebugger = Convert.ToBoolean(Configuration.Element("LaunchDebugger").Value);
Password = Configuration.Element("Password").Value;
Slot = Convert.ToInt32(Configuration.Element("Slot").Value);
Reader = Configuration.Element("Reader").Value;
TestInput = Configuration.Element("TestInput").Value;
Logging = Convert.ToBoolean(Configuration.Element("Logging").Value);
}
}
And there will be more later. so the problem is that if some element does not exist in xml i get System.NullReferenceException. So i need to check if the element is null or not. Heres one way to do this:
var value = Configuration.Element("LaunchDebugger").Value;
if (value != null)
LaunchDebugger = Convert.ToBoolean(value);
else
throw new Exception("LaunchDebugger element missing from xml!");
But doing that for every element would be just too much. So i need some good ideas how to simplify this system so it wouldn't end up in 1000 lines of code.
EDIT: Edited the last code snippet, the idea was not to set a default value, idea was to notify the user that this element whats null is missing from the xml.
The idea here comes directly from abatischev's answer so he deserves the credit.
As perscribed by Microsoft here you can just cast the XElement to the type you desire.
LaunchDebugger = (bool?)Configuration.Element("LaunchDebugger");
if you want to handle the null case I guess you could do
LaunchDebugger = (bool)(Configuration.Element("LaunchDebugger") ?? true);
or perhaps
LaunchDebugger = (bool)(Configuration.Element("LaunchDebugger") ?? false);
depending on your business logic. If you do the same coalescene for a specific type it may be appropriate to wrap this one liner in a method, extension or otherwise but I'm uncertain it would add much.
(bool)Configuration.Element("LaunchDebugger")
or
(bool?)Configuration.Element("LaunchDebugger")
should not throw exception.
See MSDN:
XElement Explicit Conversion (XElement to Boolean)
XElement Explicit Conversion (XElement to Nullable<Boolean>)
I have an extension method that I use for just this kind of thing:
public static T GetValue<T>(
this XElement #this,
XName name,
Func<XElement, T> cast,
Func<T> #default)
{
var e = #this.Element(name);
return (e != null) ? cast(e) : #default();
}
It gives you the casting required and also a default value factory.
Here's how you'd use it:
LaunchDebugger = Configuration.GetValue("LaunchDebugger",
x => Convert.ToBoolean(x), () => false);
Password = Configuration.GetValue("CMKPassword", x => (string)x, () => "");
Slot = Configuration.GetValue("CMKSlot", x => (int)x, () => -1);
Reader = Configuration.GetValue("Reader", x => (string)x, () => "");
TestInput = Configuration.GetValue("TestInput", x => (string)x, () => "");
Logging = Configuration.GetValue("Logging",
x => Convert.ToBoolean(x), () => false);
Extract the logic to a method and have overloaded methods for Int32,boolean and other data types conversion.
public static void GetElementValue(XElement xElement, string parameter, out bool value)
{
var stringValue = xElement.Element(parameter).Value;
value = false;
if (value != null)
value = Convert.ToBoolean(stringValue);
}
You can define a method to extract the value for you and do some checking on null there. So wrap the value retrieval in your own method like so:
public string GetXMLValue(XElement config, string elementName){
var element = Configuration.Element(elementName);
if(element == null)
return String.Empty;
return element.Value;
}
Of course you can extend this to work correctly with parsing to boolean etc.
How about an external method:
public static class XElementExtensions
{
public static bool AsBoolean(this XElement self, bool defaultValue)
{
if (self == null)
{
return defaultValue;
}
if (!string.IsNullOrEmpty(self.Value))
{
try
{
return XmlConvert.ToBoolean(self.Value);
}
catch
{
return defaultValue;
}
}
return defaultValue;
}
}
I've tested this with SnippetCompiler:
XElement test = new XElement("test",
new XElement("child1"),
new XElement("child2", new XText("true")),
new XElement("child3", new XText("false")),
new XElement("child4", new XText("rubbish")));
WL(test.Element("child1").AsBoolean(false)); // note, "child1" has no value (or is `""`)
WL(test.Element("child2").AsBoolean(false));
WL(test.Element("child3").AsBoolean(false));
WL(test.Element("child4").AsBoolean(false));
WL(test.Element("child5").AsBoolean(false)); // note, "child5" doesn't exist
To produce this result:
False
True
False
False
False
Add more such methods for other types and also add AsBoolean(defaultValue), as that can come in handy, when you want to default to true!
As others have stated, you can use the ?? operator to provide a value for null. This doesn't nest, though, so:
LaunchDebugger = XmlConvert.ToBoolean(Configuration.Element("LaunchDebugger").Value) ?? false;
will through a NullReferenceException if there is no such element in the XML file.
F# has a convenient feature "with", example:
type Product = { Name:string; Price:int };;
let p = { Name="Test"; Price=42; };;
let p2 = { p with Name="Test2" };;
F# created keyword "with" as the record types are by default immutable.
Now, is it possible to define a similar extension in C#?
seems it's a bit tricky, as in C# i'm not sure how to convert a string
Name="Test2"
to a delegate or expression?
public static T With<T, U>(this T obj, Expression<Func<T, U>> property, U value)
where T : ICloneable {
if (obj == null)
throw new ArgumentNullException("obj");
if (property == null)
throw new ArgumentNullException("property");
var memExpr = property.Body as MemberExpression;
if (memExpr == null || !(memExpr.Member is PropertyInfo))
throw new ArgumentException("Must refer to a property", "property");
var copy = (T)obj.Clone();
var propInfo = (PropertyInfo)memExpr.Member;
propInfo.SetValue(copy, value, null);
return copy;
}
public class Foo : ICloneable {
public int Id { get; set; }
public string Bar { get; set; }
object ICloneable.Clone() {
return new Foo { Id = this.Id, Bar = this.Bar };
}
}
public static void Test() {
var foo = new Foo { Id = 1, Bar = "blah" };
var newFoo = foo.With(x => x.Bar, "boo-ya");
Console.WriteLine(newFoo.Bar); //boo-ya
}
Or, using a copy constructor:
public class Foo {
public Foo(Foo other) {
this.Id = other.Id;
this.Bar = other.Bar;
}
public Foo() { }
public int Id { get; set; }
public string Bar { get; set; }
}
public static void Test() {
var foo = new Foo { Id = 1, Bar = "blah" };
var newFoo = new Foo(foo) { Bar = "boo-ya" };
Console.WriteLine(newFoo.Bar);
}
And a slight variation on George's excellent suggestion, that allows for multiple assignments:
public static T With<T>(this T obj, params Action<T>[] assignments)
where T : ICloneable {
if (obj == null)
throw new ArgumentNullException("obj");
if (assignments == null)
throw new ArgumentNullException("assignments");
var copy = (T)obj.Clone();
foreach (var a in assignments) {
a(copy);
}
return copy;
}
public static void Test() {
var foo = new Foo { Id = 1, Bar = "blah" };
var newFoo = foo.With(x => x.Id = 2, x => x.Bar = "boo-ya");
Console.WriteLine(newFoo.Bar);
}
I would probably use the second one since (1) any general purpose solution is going to be unnecessarily slow and convoluted; (2) it has the closest syntax to what you want (and the syntax does what you expect); (3) F# copy-and-update expressions are implemented similarly.
Maybe something like this:
void Main()
{
var NewProduct = ExistingProduct.With(P => P.Name = "Test2");
}
// Define other methods and classes here
public static class Extensions
{
public T With<T>(this T Instance, Action<T> Act) where T : ICloneable
{
var Result = Instance.Clone();
Act(Result);
return Result;
}
}
As an alternative to lambda function, you can use parameters with default values. The only minor issue is that you have to pick some default value that means do not change this parameter (for reference types), but null should be a safe choice:
class Product {
public string Name { get; private set; }
public int Price { get; private set; }
public Product(string name, int price) {
Name = name; Price = price;
}
// Creates a new product using the current values and changing
// the values of the specified arguments to a new value
public Product With(string name = null, int? price = null) {
return new Product(name ?? Name, price ?? Price);
}
}
// Then you can write:
var prod2 = prod1.With(name = "New product");
You have to define the method yourself, but that's always the case (unless you're going to use reflection, which less efficient). I think the syntax is reasonably nice too. If you want to make it as nice as in F#, then you'll have to use F# :-)
There is no native ability to do this in C# short of an extension method, but at what cost? a and b are reference types and any suggestion that b is based ("with") on a causes immediate confusion as to how many objects we are working with. Is there only one? Is b a copy of a ? Does b point to a ?
C# is not F#.
Please see a previous SO question of mine as answered by Eric Lippert:
"Amongst my rules of thumb for writing clear code is: put all side effects in statements; non-statement expressions should have no side effects."
More fluent C# / .NET