What is the idea of c# Predicate ?
Is it possible to rewrite complex condition check logic using predicates?
private bool HasChanged(object originalValue, object currentValue)
{
if ((originalValue == null && currentValue != null) ||
(originalValue != null && !originalValue.Equals(currentValue)))
{
return true;
}
return false;
}
Predicate<T> is just a delegate that takes a T and returns bool. It's the equivalent of Func<T, bool> or a method with the signature bool Method<T>(T input).
It doesn't really help you here with your method.
You can, however, simplify your method to this:
private bool HasChanged(object originalValue, object currentValue) =>
originalValue == null
? currentValue != null
: !originalValue.Equals(currentValue);
Try this:
bool HasChanged(object originalValue, object currentValue)
=> !(originalValue?.Equals(currentValue) ?? currentValue == null);
You can use a predicate to check on object agains another object declaring the predicate as an object method. Something like
class MyClass
{
public bool isValid(object obj)
{
if (obj is MyClass)
return true;
return false;
}
}
public static class Program
{
static int Main()
{
MyClass c1 = new ();
Predicate<MyClass> predicate = c1.isValid;
MyClass c2 = new ();
if (predicate(c2))
{
Console.WriteLine("c1 is valid");
}
else
{
Console.WriteLine("c1 is not valid");
}
return 0;
}
}
You could simplify this a little by flipping the logic and not attempting to cram it in to a single clause
private bool HasChanged(object originalValue, object currentValue)
{
var bothNull = originalValue == null && currentValue == null;
if (bothNull){
return false;
}
// at least one of them is not null
var areSame = originalValue?.Equals(currentValue) ?? false;
return !areSame;
}
Related
I would like to perform a test if an object is of a generic type. I've tried the following without success:
public bool Test()
{
List<int> list = new List<int>();
return list.GetType() == typeof(List<>);
}
What am I doing wrong and how do I perform this test?
If you want to check if it's an instance of a generic type:
return list.GetType().IsGenericType;
If you want to check if it's a generic List<T>:
return list.GetType().GetGenericTypeDefinition() == typeof(List<>);
As Jon points out, this checks the exact type equivalence. Returning false doesn't necessarily mean list is List<T> returns false (i.e. the object cannot be assigned to a List<T> variable).
I assume that you don't just want to know if the type is generic, but if an object is an instance of a particular generic type, without knowing the type arguments.
It's not terribly simple, unfortunately. It's not too bad if the generic type is a class (as it is in this case) but it's harder for interfaces. Here's the code for a class:
using System;
using System.Collections.Generic;
using System.Reflection;
class Test
{
static bool IsInstanceOfGenericType(Type genericType, object instance)
{
Type type = instance.GetType();
while (type != null)
{
if (type.IsGenericType &&
type.GetGenericTypeDefinition() == genericType)
{
return true;
}
type = type.BaseType;
}
return false;
}
static void Main(string[] args)
{
// True
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new List<string>()));
// False
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new string[0]));
// True
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new SubList()));
// True
Console.WriteLine(IsInstanceOfGenericType(typeof(List<>),
new SubList<int>()));
}
class SubList : List<string>
{
}
class SubList<T> : List<T>
{
}
}
EDIT: As noted in comments, this may work for interfaces:
foreach (var i in type.GetInterfaces())
{
if (i.IsGenericType && i.GetGenericTypeDefinition() == genericType)
{
return true;
}
}
I have a sneaking suspicion there may be some awkward edge cases around this, but I can't find one it fails for right now.
These are my two favorite extension methods that cover most edge cases of generic type checking:
Works with:
Multiple (generic) interfaces
Multiple (generic) base classes
Has an overload that will 'out' the specific generic type if it returns true (see unit test for samples):
public static bool IsOfGenericType(this Type typeToCheck, Type genericType)
{
Type concreteType;
return typeToCheck.IsOfGenericType(genericType, out concreteType);
}
public static bool IsOfGenericType(this Type typeToCheck, Type genericType, out Type concreteGenericType)
{
while (true)
{
concreteGenericType = null;
if (genericType == null)
throw new ArgumentNullException(nameof(genericType));
if (!genericType.IsGenericTypeDefinition)
throw new ArgumentException("The definition needs to be a GenericTypeDefinition", nameof(genericType));
if (typeToCheck == null || typeToCheck == typeof(object))
return false;
if (typeToCheck == genericType)
{
concreteGenericType = typeToCheck;
return true;
}
if ((typeToCheck.IsGenericType ? typeToCheck.GetGenericTypeDefinition() : typeToCheck) == genericType)
{
concreteGenericType = typeToCheck;
return true;
}
if (genericType.IsInterface)
foreach (var i in typeToCheck.GetInterfaces())
if (i.IsOfGenericType(genericType, out concreteGenericType))
return true;
typeToCheck = typeToCheck.BaseType;
}
}
Here's a test to demonstrate the (basic) functionality:
[Test]
public void SimpleGenericInterfaces()
{
Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IEnumerable<>)));
Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IQueryable<>)));
Type concreteType;
Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IEnumerable<>), out concreteType));
Assert.AreEqual(typeof(IEnumerable<string>), concreteType);
Assert.IsTrue(typeof(Table<string>).IsOfGenericType(typeof(IQueryable<>), out concreteType));
Assert.AreEqual(typeof(IQueryable<string>), concreteType);
}
You can use shorter code using dynamic althougth this may be slower than pure reflection:
public static class Extension
{
public static bool IsGenericList(this object o)
{
return IsGeneric((dynamic)o);
}
public static bool IsGeneric<T>(List<T> o)
{
return true;
}
public static bool IsGeneric( object o)
{
return false;
}
}
var l = new List<int>();
l.IsGenericList().Should().BeTrue();
var o = new object();
o.IsGenericList().Should().BeFalse();
return list.GetType().IsGenericType;
public static string WhatIsMyType<T>()
{
return typeof(T).NameWithGenerics();
}
public static string NameWithGenerics(this Type type)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
if (type.IsArray)
return $"{type.GetElementType()?.Name}[]";
if (!type.IsGenericType)
return type.Name;
var name = type.GetGenericTypeDefinition().Name;
var index = name.IndexOf('`');
var newName = index == -1 ? name : name.Substring(0, index);
var list = type.GetGenericArguments().Select(NameWithGenerics).ToList();
return $"{newName}<{string.Join(",", list)}>";
}
Now test with this:
Console.WriteLine(WhatIsMyType<IEnumerable<string>>());
Console.WriteLine(WhatIsMyType<List<int>>());
Console.WriteLine(WhatIsMyType<IList<int>>());
Console.WriteLine(WhatIsMyType<List<ContentBlob>>());
Console.WriteLine(WhatIsMyType<int[]>());
Console.WriteLine(WhatIsMyType<ContentBlob>());
Console.WriteLine(WhatIsMyType<Dictionary<string, Dictionary<int, int>>>());
and you will get
IEnumerable<String>
List<Int32>
IList<Int32>
List<ContentBlob>
Int32[]
ContentBlob
Dictionary<String,Dictionary<Int32,Int32>>
I have problem with CustomType in Fluent NHibernate.
I have to save as Json a dictionary to my database.
I created a customType for this that implements IUserType interface.
There is no problem to save dictionary to database for first time, but when i try to update collection, nHibernate dont set a property as dirty and dont update it.
My Equals and GetHashCode methods
public new bool Equals(object x, object y)
{
if (x == null && y == null)
return true;
if (x == null || y == null)
return false;
if (!(x is IDictionary<K, Z>) || !(y is IDictionary<K, Z>))
return false;
var dic1 = (x as IDictionary<K, Z>).OrderBy(z=> z.Key);
var dic2 = (y as IDictionary<K, Z>).OrderBy(z => z.Key);
return dic1.SequenceEqual(dic2);
}
public int GetHashCode(object x)
{
if (x == null)
return 0;
return x.GetHashCode();
}
The objects passed to equals method are always the same (recently modified) two object.
Anyone have a idea what i'm doing wrong ?
Rest of IUserType implementation code:
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
if (names.Length != 1)
throw new InvalidOperationException("Only expecting one column...");
var val = rs[names[0]] as string;
if (val != null && !string.IsNullOrWhiteSpace(val))
{
return JsonConvert.DeserializeObject<T>(val, JSonSerializableTypeSerializer.Settings);
}
return null;
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
var parameter = (DbParameter)cmd.Parameters[index];
if (value == null)
{
parameter.Value = DBNull.Value;
}
else
{
parameter.Value = JsonConvert.SerializeObject(value, JSonSerializableTypeSerializer.Settings);
}
}
public object DeepCopy(object value)
{
return value;
}
public object Replace(object original, object target, object owner)
{
return original;
}
public object Assemble(object cached, object owner)
{
return cached;
}
public object Disassemble(object value)
{
return value;
}
public SqlType[] SqlTypes
{
get
{
return new SqlType[] { new StringClobSqlType() };
}
}
public Type ReturnedType
{
get { return typeof(T); }
}
public bool IsMutable
{
get { return true; }
}
Maybe I am wrong, but I guess you have returned false while implementing IUserType.IsMutable.
Since your user type returns a Dictionary, which is a mutable type, and which you do indeed mutate, your user type must return true for its IsMutable property.
C# 6.0 code:
public bool HasLeaderOtherThanSelf
{
return LeaderMembership?.AthleteId != App.CurrentAthlete.Id;
}
What is correct way to implement it in C# 4?
To return null or false back if LeaderMembership is null?
In C# 4.0:
public bool HasLeaderOtherThanSelf
{
return LeaderMembership != null && LeaderMembership.AthleteId != App.CurrentAthlete.Id;
}
OR
public bool? HasLeaderOtherThanSelf
{
if(LeaderMembership == null)
{
return null;
}
return LeaderMembership.AthleteId != App.CurrentAthlete.Id;
}
You would return false back.
public bool HasLeaderOtherThanSelf
{
if (LeaderMembership != null)
return LeaderMembership.AthleteId != App.CurrentAthlete.Id;
return false;
}
Which can be simplified to:
public bool HasLeaderOtherThanSelf
{
return LeaderMembership != null && LeaderMembership.AthleteId != App.CurrentAthlete.Id;
}
If LeaderMembership is null, the result of LeaderMembership?.AthleteId will be a null value of type nullable int (assuming AthleteId is an integer).
Presumably the App.CurrentAthlete.Id is also an integer, so the comparison of a null value of type nullable int with an int will be false.
Like this:
public bool HasLeaderOtherThanSelf
{
if(LeaderMembership != null)
return LeaderMembership.AthleteId != App.CurrentAthlete.Id;
return false;
}
Or if you want to be able to return null you should change your HasLeaderOtherThanSelf type to
Nullable Bool (bool?):
public bool? HasLeaderOtherThanSelf
{
if(LeaderMembership != null)
return LeaderMembership.AthleteId != App.CurrentAthlete.Id;
return null;
}
try with extension
public static TValue GetOrDefault<TObject, TValue>(this TObject obj, Func<TObject, TValue> getter, TValue defaultValue = default(TValue))
where TObject : class
{
return obj == null ? defaultValue : getter(obj);
}
you can use it as:
public bool HasLeaderOtherThanSelf
{
return LeaderMembership.GetOrDefault(x => x.AthleteId) != App.CurrentAthlete.Id;
}
or if you want to return null:
public static TValue? GetOrDefault<TObject, TValue>(this TObject obj, Func<TObject, TValue> getter, TValue? defaultValue = default(TValue?))
where TObject : class
where TValue : struct
{
return obj == null ? defaultValue : getter(obj);
}
Your C# 6 code translates to
public bool HasLeaderOtherThanSelf
{
var leaderMembership = LeaderMembership;
return (leaderMembership == null ? default(int?) : leaderMembership.AthleteId)
!= App.CurrentAthlete.Id;
}
Note that your code reads LeaderMembership only once, and to accurate emulate that in C# <6, you need an additional local variable.
Note if LeaderMembership is null and App.CurrentAthlete.Id is non-null, your existing code returns true, but most of the other answers return false for that case. false is probably a better answer, but not an accurate translation of your existing code.
In C# 4 it look like:
public bool HasLeaderOtherThanSelf
{
return LeaderMembership != null && LeaderMembership?.AthleteId != App.CurrentAthlete.Id;
}
But use "hardcode" is not good practice) Will be better do something like this:
First variant:
public bool IsNullOrEquivalent<T>(T target, Func<T, bool> comparer)
where T : class
{
return target == null
&& comparer(target);
}
that you can use like:
var result = new NonExtensionComparer().IsNullOrEquivalent(LeaderMembership, e => e.AthleteId == App.CurrentAthlete.Id);
Second varian (extension):
public static bool IsNullOrEquivalent<T>(this T target, Func<T, bool> comparer)
{
return target == null
&& comparer(target);
}
use:
var result = LeaderMembership.IsNullOrEquivalent(e => e.AthleteId == App.CurrentAthlete.Id);
I'm trying to run the following code but get a casting error.
How can I rewrite my code to achive the same ?
boolResult= (bool?)dataReader["BOOL_FLAG"] ?? true;
intResult= (int?)dataReader["INT_VALUE"] ?? 0;
Thanks
Use the "IsDbNull" method on the data reader... for example:
bool? result = dataReader.IsDbNull(dataReader["Bool_Flag"]) ? null : (bool)dataReader["Bool_Flag"]
Edit
You'd need to do something akin to:
bool? nullBoolean = null;
you'd have
bool? result = dataReader.IsDbNull(dataReader["Bool_Flag"]) ? nullBoolean : (bool)dataReader["Bool_Flag"]
Consider doing it in a function.
Here's something I used in the past (you can make this an extension method in .net 4):
public static T GetValueOrDefault<T>(SqlDataReader dataReader, System.Enum columnIndex)
{
int index = Convert.ToInt32(columnIndex);
return !dataReader.IsDBNull(index) ? (T)dataReader.GetValue(index) : default(T);
}
Edit
As an extension (not tested, but you get the idea), and using column names instead of index:
public static T GetValueOrDefault<T>(this SqlDataReader dataReader, string columnName)
{
return !dataReader.IsDBNull(dataReader[columnName]) ? (T)dataReader.GetValue(dataReader[columnName]) : default(T);
}
usage:
bool? flag = dataReader.GetValueOrDefault("BOOL_COLUMN");
There's an answer here that might be helpful:
https://stackoverflow.com/a/3308515/1255900
You can use the "as" keyword. Note the caution mentioned in the comments.
nullableBoolResult = dataReader["BOOL_FLAG"] as bool?;
Or, if you are not using nullables, as in your original post:
boolResult = (dataReader["BOOL_FLAG"] as bool?) ?? 0;
bool? boolResult = null;
int? intResult = null;
if (dataReader.IsDBNull(reader.GetOrdinal("BOOL_FLAG")) == false)
{
boolResult = dataReader.GetBoolean(reader.GetOrdinal("BOOL_FLAG"));
}
else
{
boolResult = true;
}
if (dataReader.IsDBNull(reader.GetOrdinal("INT_VALUE")) == false)
{
intResult= dataReader.GetInt32(reader.GetOrdinal("INT_VALUE"));
}
else
{
intResult = 0;
}
I'm sure I found the inspiration for this somewhere around the interweb but I can't seem to find the original source anymore. Anyway, below you find a utility class which allows to define an extension method on DataReader, like this:
public static class DataReaderExtensions
{
public static TResult Get<TResult>(this IDataReader reader, string name)
{
return reader.Get<TResult>(reader.GetOrdinal(name));
}
public static TResult Get<TResult>(this IDataReader reader, int c)
{
return ConvertTo<TResult>.From(reader[c]);
}
}
Usage:
reader.Get<bool?>("columnname")
or
reader.Get<int?>(5)
Here's the enabling utility class:
public static class ConvertTo<T>
{
// 'Factory method delegate', set in the static constructor
public static readonly Func<object, T> From;
static ConvertTo()
{
From = Create(typeof(T));
}
private static Func<object, T> Create(Type type)
{
if (!type.IsValueType) { return ConvertRefType; }
if (type.IsNullableType())
{
return (Func<object, T>)Delegate.CreateDelegate(typeof(Func<object, T>), typeof(ConvertTo<T>).GetMethod("ConvertNullableValueType", BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(new[] { type.GetGenericArguments()[0] }));
}
return ConvertValueType;
}
// ReSharper disable UnusedMember.Local
// (used via reflection!)
private static TElem? ConvertNullableValueType<TElem>(object value) where TElem : struct
{
if (DBNull.Value == value) { return null; }
return (TElem)value;
}
// ReSharper restore UnusedMember.Local
private static T ConvertRefType(object value)
{
if (DBNull.Value != value) { return (T)value; }
return default(T);
}
private static T ConvertValueType(object value)
{
if (DBNull.Value == value)
{
throw new NullReferenceException("Value is DbNull");
}
return (T)value;
}
}
EDIT: makes use of the IsNullableType() extension method defined like so:
public static bool IsNullableType(this Type type)
{
return
(type.IsGenericType && !type.IsGenericTypeDefinition) &&
(typeof (Nullable<>) == type.GetGenericTypeDefinition());
}
Here's my shot at an extension method. Column name semantics and falls back to default(T) when a null is encountered.
public static class DbExtensions
{
public static T ReadAs<T>(this IDataReader reader, string col)
{
object val = reader[col];
if (val is DBNull)
{
// Use the default if the column is null
return default(T);
}
return (T)val;
}
}
Here is the sample usage. Remember that despite string being a reference type, it will still fail to cast to null from a DBNull. The same is true with int?.
public Facility Bind(IDataReader reader)
{
var x = new Facility();
x.ID = reader.ReadAs<Guid>("ID");
x.Name = reader.ReadAs<string>("Name");
x.Capacity = reader.ReadAs<int?>("Capacity");
x.Description = reader.ReadAs<string>("Description");
x.Address = reader.ReadAs<string>("Address");
return x;
}
using extension method:
public static T GetValueOrDefault <T> (this SqlDataReader reader, string column) {
var isDbNull = reader[column] == DBNull.Value;
return !isDbNull ? (T) reader[column] : default (T);
}
Remember that a DBNull is not the same thing as null, so you cannot cast from one to the other. As the other poster said, you can check for DBNull using the IsDBNull() method.
Try this version. It performs some basic conversion and manages default values as well.
public bool IsList(object value)
{
Type type = value.GetType();
// Check if type is a generic list of any type
}
What's the best way to check if the given object is a list, or can be cast to a list?
For you guys that enjoy the use of extension methods:
public static bool IsGenericList(this object o)
{
var oType = o.GetType();
return (oType.IsGenericType && (oType.GetGenericTypeDefinition() == typeof(List<>)));
}
So, we could do:
if(o.IsGenericList())
{
//...
}
using System.Collections;
if(value is IList && value.GetType().IsGenericType) {
}
bool isList = o.GetType().IsGenericType
&& o.GetType().GetGenericTypeDefinition() == typeof(IList<>));
public bool IsList(object value) {
return value is IList
|| IsGenericList(value);
}
public bool IsGenericList(object value) {
var type = value.GetType();
return type.IsGenericType
&& typeof(List<>) == type.GetGenericTypeDefinition();
}
Here's an implementation that works in .NET Standard, and works against interfaces:
public static bool ImplementsGenericInterface(this Type type, Type interfaceType)
{
return type
.GetTypeInfo()
.ImplementedInterfaces
.Any(x => x.GetTypeInfo().IsGenericType && x.GetGenericTypeDefinition() == interfaceType);
}
And here are the tests (xunit):
[Fact]
public void ImplementsGenericInterface_List_IsValidInterfaceTypes()
{
var list = new List<string>();
Assert.True(list.GetType().ImplementsGenericInterface(typeof(IList<>)));
Assert.True(list.GetType().ImplementsGenericInterface(typeof(IEnumerable<>)));
Assert.True(list.GetType().ImplementsGenericInterface(typeof(IReadOnlyList<>)));
}
[Fact]
public void ImplementsGenericInterface_List_IsNotInvalidInterfaceTypes()
{
var list = new List<string>();
Assert.False(list.GetType().ImplementsGenericInterface(typeof(string)));
Assert.False(list.GetType().ImplementsGenericInterface(typeof(IDictionary<,>)));
Assert.False(list.GetType().ImplementsGenericInterface(typeof(IComparable<>)));
Assert.False(list.GetType().ImplementsGenericInterface(typeof(DateTime)));
}
if(value is IList && value.GetType().GetGenericArguments().Length > 0)
{
}
Based on Victor Rodrigues' answer, we can devise another method for generics. In fact, the original solution can be reduced to only two lines:
public static bool IsGenericList(this object Value)
{
var t = Value.GetType();
return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(List<>);
}
public static bool IsGenericList<T>(this object Value)
{
var t = Value.GetType();
return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(List<T>);
}
I'm using the following code:
public bool IsList(Type type) => type.IsGenericType && (
(type.GetGenericTypeDefinition() == typeof(List<>))
|| (type.GetGenericTypeDefinition() == typeof(IList<>))
);
Probably the best way would be to do something like this:
IList list = value as IList;
if (list != null)
{
// use list in here
}
This will give you maximum flexibility and also allow you to work with many different types that implement the IList interface.