Update arbitrary member with only non null values - c#

I have two classes with no inheritance relationship (well, excepting being Object):
class A
{
Member1 m1;
Member2 m2;
}
class B
{
Member1 m3;
Member2 m4;
}
Each member of a class is paierd with a member of the same arbitrary type in the other class, it might or might not have the same name, it can be null.
I would like to do something like this:
if (b.m3 != null) a.m1 = b.m3;
just to update values that are not null, where a is an instance of class A and b is an instance of class B.
The number of members to update might grow with time, I'd like some more general and elegant way to do the update, something to be used like this:
a.Update(d => d.m1, b.m3)
I have tried with an extension method:
public static void Update<TSource, TKey>(this TSource source, Func<TSource, TKey> key, TKey newValue)
where TSource : A
{
if (newValue != null)
{
key(source) = newValue;
}
}
but there is clearly something wrong because I get an exception saying that the left-hand side of the the equality key(source) must be a variable.
Any ideas?

The reason this doesn't work is because a Func is literally a function that returns a value. When called you have to assign that value to a variable, thus the error message you are getting. Instead of a Func you could use an Action and pass both the source and the key to it.
public static void Update<TSource, TKey>(
this TSource source,
Action<TSource, TKey> action,
TKey newValue)
where TSource : A
{
if (newValue != null)
{
action(source, newValue);
}
}
Then call it like this.
a.Update((myA, val) => myA.m1 = val, b.m3);
But really it would be simpler to just do the following
a.m1 = b.m3 ?? a.m1;
That will assign b.m3 to a.m1 if it is not null. Otherwise it just assigns a.m1 to itself.
Although for this specific case you should look into mapping libraries that can handle this type of thing for you.

You could do something like this
Member1 m1;
public Setm1(Member1 in)
{
if (in != null) m1 = in;
}
Then your code is very simple:
a.Setm1(b.m3);
Or you could use the accessor (with the same code) and you would have
public Member1 Setm1
{
set { if (value != null) m1 = value;
}
a.Setm1 = b.m3;

Related

Is there any way to perform a sort of null coalesce on a property in C#?

I'm not quite sure how to phrase this question but the scenario is as follows:
Say I have the following class:
public class SampleClass
{
public int Number { get; set; }
}
I know you can null coalesce the containing class:
SampleClass newSampleClass = possibleNullSampleClass ?? notNullSampleClass;
Is there any way to perform a sort of null coalesce on the property so I don't have to do this:
int? num = sampleClass != null ? new int?(sampleClass.Number) : 5;
It seems like it would be very useful to have something like a ??? operator to perform this check so I could do:
int? num = sampleClass.Number ??? 5;
Is anything like that possible in C#?
Currently there is no such an operator. But in C# 6 "safe-navigation" operator will appear and you'll be able to write
int number = sampleClass?.Number;
This code won't fail with NullRef even if sampleClass equals null. For now you can use the following extension method that extracts value from an object and encapsulates null-check:
public static TResult Maybe<TSource, TResult>(
this TSource source, Func<TSource, TResult> produceResult, Func<TResult> produceDefault)
where TSource : class
{
return source == null ? produceDefault() : produceResult(source);
}
and use it as follows:
int numberOrFive = sampleClass.Maybe(c => c.Number, () => 5);
There is no existing operator to do that. You have shown one perfectly acceptable way of handling the problem.
If you wanted, you could wrap the logic in a method, but I'm not sure if that'd actually be worth the effort or not:
public static TResult Access<TSource, TResult>(
TSource obj, Func<TSource, TResult> selector, TResult defaultIfNull)
where TSource : class
{
if (obj == null)
return defaultIfNull;
else
return selector(obj);
}
SampleClass sampleClass = null;
int num = Access(sampleClass, s => s.Number, 5);
(If you wanted, you could consider making that an extension method as well, although I personally am wary of extension methods on all classes. Also consider other names, such as Use.)
I'm going to propose a modification of Servy's post. I think his method would prove useful if it could handle the general case, where there can be a null anywhere up the object chain.
public static TResult Access<TSource, TResult>(
TSource obj, Func<TSource, TResult> selector, TResult defaultIfNull)
where TSource : class
{
TResult result;
try
{
result = selector(obj);
}
catch ( NullReferenceException)
{
result = defaultIfNull;
}
return result;
}
This way if you are trying to access
ZipCode = Customer.Address.ZipCode;
You are protected if either Customer or Address is null
You can't do that in C#. You need to explicitly test for nullity:
MyWidget x ;
int? v = x == null ? (int?)x.SomeProperty : (int?) null ;
If you really think it would be useful, you could log your suggestion at Microsoft Connect:
http://connect.microsoft.com/VisualStudio
I'm willing to be that they thought about it and decided it wasn't sufficiently useful to build into the language.
You can totally do this:
var x = (myObject ?? DefaultObject).Field;
And this...
var x = (myObject == null) ? myObject.Field : defaultValue;

Converting a null type to a list (error handling)

So, the title is a bit misleading and I'll sort it out first.
Consider the following piece of code:
public static ADescription CreateDescription(string file, string name, params string[] othername)
{
return new ADescription(file, name, othername.ToList<string>());
}
This will throw a System.ArgumentNullException in a case where the user deliberately enters a null at the end. For e.g.:
ADescription.CreateDescription("file", "name", null); // example
Now I have a property that basically gets & sets the othername list. My concern is that I will have to check at every stage like (in the property, as well as in this method):
if (othername == null){
// do nothing
}
else{
othername.ToList<string>; // for example
}
because, null is acceptable for othername. Is there any way that c# natively provides this capability where if othername is null, then it wouldn't really operate ToList() on that.
You can use a ternary operator:
return new ADescription(file, name, othername==null?null:othername.ToList<string>());
Or create an extension method as described in the accepted response here Possible pitfalls of using this (extension method based) shorthand:
public static class IfNotNullExtensionMethod
{
public static U IfNotNull<T, U>(this T t, Func<T, U> fn)
{
return t != null ? fn(t) : default(U);
}
}
Your code would be:
return new ADescription(file, name, othername.IfNotNull(on => on.ToList());
You could make an extension method to handle this:
public static class MyExtensionMethods
{
public static List<T> ToListIfNotNull<T>(this IEnumerable<T> enumerable)
{
return (enumerable != null ? new List<T>(enumerable) : null);
}
}
Then you can substitute the extension method wherever you would otherwise use ToList().
return new ADescription(file, name, othername.ToListIfNotNull());

Multiple generic types in same list and calling their methods

I'm making an object validation framework in my spare time to learn a few things and maybe use it for some school projects.
I have my generic Rule class, which looks something like this :
class Rule<T>
{
string propertyName;
Func<T, bool> ruleLambda;
bool IsBroken(T value)
{
return ruleLambda(value);
}
}
An object that would be validated would look a bit like this :
class Example
{
List<Rule<?>> MyRules; // can take all types of rules
List<Rule<T>> Validate<T>(string propertyName, T value)
{
List<Rule<T>> brokenRules = new List<Rule<T>>();
foreach (Rule rule in MyRules.Where(r => r.propertyName == propertyName))
{
if (rule.IsBroken(value))
brokenRules.Add(rule);
}
return brokenRules;
}
}
Where the T value argument would be the value of one of the Example class's properties, which can be of any type.
The Validate<T> method is called whenever a property is set.
The problem lies with the class's list of rules. Specifically the List<Rule<?>> line above. I want to store all the rules for a given class in the same list.
Alas, C# doesn't have a wildcard for generic types like in Java.
How should I do this?
A non-generic interface or base class utilizing objects instead of T could work, but how would I call the generic Rule's IsBroken method and not the non-generic one?
I would store your rules as object inside the Example class and use Enumerable.OfType<T> to find the matching rules for a given type:
class Example
{
private List<object> rules;
List<Rule<T>> Validate<T>(string propertyName, T value)
{
return this.rules.OfType<Rule<T>>()
.Where(r => r.PropertyName == propertyName && r.IsBroken(value))
.ToList();
}
}
In cases where I've needed something like this, I use interfaces or non-generic base classes. For example, you could create an interface:
public interface IRule
{
//non-generic properties & methods
}
public class Rule<T> : IRule
{
//implementation
}
then create a list of the interfaces:
private List<IRule> MyRules;
If you want to make converting from the interface to the generic easy, you could add an extension method:
public static Rule<T> ToGeneric<T>(this IRule rule)
{
return rule as Rule<T>;
}
I've tried a few things and I've found something that works pretty well for my needs. I have Rule<T> inherit from a base abstract rule class, with a generic IsBroken method:
abstract class Rule
{
string propertyName;
Func<object, bool> objectRule;
bool IsBroken<T>(T value)
{
Rule<T> rule = this as Rule<T>;
if (rule == null)
return objectRule(value);
return rule.IsBroken(value);
}
}
As you can see, I try to convert the base class to its generic counterpart using the generic type parameter in the IsBroken method.
Also, when creating a Rule<T> instance, I send a Func<object, bool> to its base class protected constructor:
public Rule(string propertyName, Func<T, bool> ruleLambda)
: base(propertyName, ConvertToObjectFunc(ruleLambda))
{
}
With the conversion method looking like this:
static Func<object, bool> ConvertToObjectFunc(Func<T, bool> func)
{
return new Func<object, bool>(o => func((T)o));
}
However, if it can't cast o to type T, it crashes. So I wrote this... thing:
static Func<object, bool> ConvertToObjectFunc(Func<T, bool> func)
{
return new Func<object, bool>
(
o =>
{
try
{
T obj = (T)o;
return func(obj);
}
catch { return true; } // rule is broken by default
}
);
}
It's pretty ugly, but it works. Hope this can help anybody else.

Add to Collection if Not Null

I have a very large object with many nullable-type variables. I also have a dictionary which I want to fill up with this object's non-null variables.
The code will look something like this
if (myObject.whatever != null)
{
myDictionary.Add("...",myObject.whatever);
}
if (myObject.somethingElse != null)
{
myDictionary.Add("...",myObject.somethingElse);
...
EDIT (Sorry messed up the code)
When we repeat this for the umpteenth time we get a mess of very long code. Is there some shorter way I could write this mess? I know about the Conditional Operator (aka ?) but that's just for assignments. Is there something like that for adding to a collection?
How about an extension method for your dictionary?
public static void AddIfNotNull<T,U>(this Dictionary<T,U> dic, T key, U value)
where U : class {
if (value != null) { dic.Add(key, value); }
}
You could then do this:
myDictionary.AddIfNotNull("...",myObject.whatever);
I'd recommend writing an extension method:
public static class MyExtensions
{
public static void AddIfNotNull<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value)
{
if ((object)value != null)
dictionary.Add(key, value);
}
}
Using (object)value != null ensures that this works as you'd expect with nullable types, (e.g. int?) value types, (e.g. int) and reference types (e.g. SomeClass). If you compare it to default(TValue), then an int of 0 will not be added, even though it's not null. If you include a TValue : class requirement, you can't use Nullable<T> as the type, which it sounds like is your most common usage.
You can make a method that hides your if:
AddIfNotNull(myDictionary, "...", myObject.whatever);
private static void AddIfNotNull<K,T>(
IDictionary<K,T> myDictionary
, K key
, T value) {
if (value != default(T)) {
myDictionary.Add(key, value);
}
}
You can earn some "points for style" by making the method an extension (you need to add it to a static class then):
private static void AddIfNotNull<K,T>(
this IDictionary<K,T> myDictionary
, K key
, T value) {
if (value != default(T)) {
myDictionary.Add(key, value);
}
}
myDictionary.AddIfNotNull(myDictionary, "...", myObject.whatever);
If you know that you are inserting only reference type objects, replace default(T) with null and add a class T constraint to the generic.
public void addToDict(string ?myObj, Dictionary<,> myDict) {
if (myObj != null)
myDict.Add("...", myObj);
}
addToDict(myObject.whatever, myDict);
addToDict(myObject.somethignElse, myDict);
etc

Is there a way of making C# binding work statically?

This probably applies to other places, but in WinForms, when I use binding I find many methods want to take the name of the property to bind to. Something like:
class Person
{
public String Name { get { ... } set { ... } }
public int Age { get { ... } set { ... } }
}
class PersonView
{
void Bind(Person p)
{
nameControl.Bind(p,"Name");
ageControl.Bind(p,"Age");
}
}
The big problem I keep having with this is that "Name" and "Age" are specified as strings. This means the compiler is no help if someone renames one of Person's properties. The code will compile fine, but the bindings will be broken.
Is there a standard way of solving this that I've missed? It feels like I need some keyword, maybe called stringof to match the existing typeof. You could use it something like:
ageControl.Bind(p,stringof(p.Age).Name);
stringof could return some class that has properties for getting the full path, part of the path, or the string so you can parse it up yourself.
Is something like this already do-able?
Have a look at this code snippet I've posted in another question, it can help you! (But only, if you are using .NET 3.5)
Best Regards
Oliver Hanappi
You can do that with expression trees, as explained in this question
protected static string GetPropertyName<TSource, TResult>(Expression<Func<TSource, TResult>> expression)
{
if (expression.NodeType == ExpressionType.Lambda && expression.Body.NodeType == ExpressionType.MemberAccess)
{
PropertyInfo prop = (expression.Body as MemberExpression).Member as PropertyInfo;
if (prop != null)
{
return prop.Name;
}
}
throw new ArgumentException("expression", "Not a property expression");
}
...
ageControl.Bind(p, GetPropertyName((Person p) => p.Age));
You can use Expressions to get compiler-checked bindings.
For example, in one of current projects we set up bindings like this:
DataBinder
.BindToObject(this)
.ObjectProperty(c => c.IsReadOnly)
.Control(nameTextBox, n => n.ReadOnly)
.Control(addressControl, n => n.ReadOnly)
Code supporting this style is separated into several classes:
public static class DataBinder
{
public static DataBinderBindingSourceContext<TDataSource> BindToObject<TDataSource>(TDataSource dataSource)
{
return new DataBinderBindingSourceContext<TDataSource>(dataSource);
}
}
public class DataBinderBindingSourceContext<TDataSource>
{
public readonly object DataSource;
public DataBinderBindingSourceContext(object dataSource)
{
DataSource = dataSource;
}
public DataBinderControlContext<TDataSource, TProperty> ObjectProperty<TProperty>(Expression<Func<TDataSource, TProperty>> property)
{
return new DataBinderControlContext<TDataSource, TProperty>(this, property);
}
}
public class DataBinderControlContext<TDataSource, TProperty>
{
readonly DataBinderBindingSourceContext<TDataSource> BindingSourceContext;
readonly string ObjectProperty;
public DataBinderControlContext
(
DataBinderBindingSourceContext<TDataSource> bindingSourceContext,
Expression<Func<TDataSource, TProperty>> objectProperty
)
{
BindingSourceContext = RequireArg.NotNull(bindingSourceContext);
ObjectProperty = ExpressionHelper.GetPropertyName(objectProperty);
}
public DataBinderControlContext<TDataSource, TProperty> Control<TControl>(TControl control, Expression<Func<TControl, TProperty>> property)
where TControl : Control
{
var controlPropertyName = ExpressionHelper.GetPropertyName(property);
control.DataBindings.Add(controlPropertyName, BindingSourceContext.DataSource, ObjectProperty, true);
return this;
}
}
public static class ExpressionHelper
{
public static string GetPropertyName<TResult>(Expression<Func<TResult>> property)
{
return GetMemberNames(((LambdaExpression)property).Body).Skip(1).Join(".");
}
public static string GetPropertyName<T, TResult>(Expression<Func<T, TResult>> property)
{
return GetMemberNames(((LambdaExpression)property).Body).Join(".");
}
static IEnumerable<string> GetMemberNames(Expression expression)
{
if (expression is ConstantExpression || expression is ParameterExpression)
yield break;
var memberExpression = (MemberExpression)expression;
foreach (var memberName in GetMemberNames(memberExpression.Expression))
yield return memberName;
yield return memberExpression.Member.Name;
}
}
public static class StringExtentions
{
public static string Join(this IEnumerable<string> values, string separator)
{
if (values == null)
return null;
return string.Join(separator, values.ToArray());
}
}
You could use reflection to find the name ;-)
This of course would be a circular reference, you'd use the name that you think it is to find the same name (or to not find anything, meaning the property was renamed... But there's an idea (or rather, a trick) : by making a do-nothing reference to the property you wish to use, you'd get compile time confirmation that it is still there. Only problem is if someone merely swap various property names around; in that case, the names still exist (no compile-time error), but have different application-level semantics (possible surprises in the application's output)

Categories