Correctly distinguish between bool? and bool in C# - c#

I am trying to find out if a variable is either a simple bool or a Nullable<bool>.
It seems that
if(val is Nullable<bool>)
returns true for both bool and Nullable<bool> variables and
if(val is bool)
also returns true for both bool and Nullable<bool>.
Basically, I am interesting in finding out if a simple bool variable is true OR if a Nullable<bool> variable is not null.
What's the way to do this?
Here is the full code:
List<string> values = typeof(InstViewModel).GetProperties()
.Where(prop => prop != "SubCollection" && prop != "ID" && prop != "Name" && prop != "Level")
.Select(prop => prop.GetValue(ivm, null))
.Where(val => val != null && (val.GetType() != typeof(bool) || (bool)val == true)) //here I'm trying to check if val is bool and true or if bool? and not null
.Select(val => val.ToString())
.Where(str => str.Length > 0)
.ToList();
The InstViewModel object:
public class InstViewModel
{
public string SubCollection { get; set; }
public string ID { get; set; }
public string Name { get; set; }
public string Level { get; set; }
public bool Uk { get; set; }
public bool Eu { get; set; }
public bool Os { get; set; }
public Nullable<bool> Mobiles { get; set; }
public Nullable<bool> Landlines { get; set; }
public Nullable<bool> UkNrs { get; set; }
public Nullable<bool> IntNrs { get; set; }
}
The point of my code here is to find out if all of the object's values are null (more specifically, to find out any values that are not null and save them in a List<string>). This presents a complication in the lambda expression, however, when trying to distinguish between bool and bool? types in my object (second Where statement).
Additionally, since the object contains some string types as well, I am trying to exclude those in my first .Where statement (which I am probably not doing right at present as it doesn't seem to be working). But my main goal is to distinguish between bool and bool? types.

There is a simple way to check whether a variable is declared as T or T?:
private static bool IsNullable<T>(T val)
{
return false;
}
private static bool IsNullable<T>(T? val)
where T : struct
{
return true;
}
Usage:
bool? val = false;
if (IsNullable(val))
{
...
}
EDIT
Try the following code for edited question:
var boolProps = typeof (InstViewModel).GetProperties()
.Where(prop => prop.PropertyType == typeof(bool))
.Select(prop => (bool)prop.GetValue(ivm, null))
.Select(v => v ? v.ToString() : String.Empty);
var nullableBoolProps = typeof(InstViewModel).GetProperties()
.Where(prop => prop.PropertyType == typeof(bool?))
.Select(prop => (bool?)prop.GetValue(ivm, null))
.Select(v => v.HasValue ? v.ToString() : String.Empty);
List<string> values = boolProps.Concat(nullableBoolProps)
.Where(str => str.Length != 0)
.ToList();

Code for getting class instance values:
// create class instance
InstViewModel model = new InstViewModel()
{
Uk = true,
UkNrs = false,
};
// check all boolean fields are false or null
bool isAllNullOrFalse = (from property in typeof(InstViewModel).GetProperties()
let type = property.PropertyType
let isBool = type == typeof(bool)
where isBool || type == typeof(bool?)
let value = property.GetValue(model)
select value == null || (isBool && bool.Equals(value, false))).All(e => e);
Console.WriteLine("All values are null or false = {0}", isAllNullOrFalse);

typeof(InstViewModel).GetProperties()
.Select(prop => prop.GetValue(ivm, null))
At this point, you have a sequence of type object. Each element of that sequence will be an object that can be one of:
An instance of a reference type.
A boxed instance of a value type.
null.
The null case can happen either because you had a null value for a property which was of reference type, or a null value for a property that was a nullable value type; there's no way to tell the difference at here. Likewise there's no way to tell the difference between a boxed bool that came from a bool value or a boxed bool that came from a bool? value.
You need to examine the type of the property, not the property's value:
isNullableProperty = property.PropertyType.IsGenericType
&& property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>);
But to just filter to only bool and bool? then:
typeof(InstViewModel).GetProperties()
.Where(
prop => prop.PropertyType == typeof(bool)
|| prop.PropertyType == typeof(bool?))

You can distinguish the boolean and nullable boolean properties before you evaluate them. Then there is no need to worry about whether they evaluate to a bool or a Nullable<bool>:
var nullableBooleanProperties = typeof(InstViewModel).Where(prop => prop.PropertyType == typeof(bool?));
Then you can simply write these out to a list of strings:
var values = nullableBooleanProperties.Select(prop => prop.GetValue(ivm)).Where(val => val != null).Select(val => val.ToString());
Putting these together gives:
var values = typeof(InstViewModel).Where(prop => prop.PropertyType == typeof(bool?))
.Select(prop => prop.GetValue(ivm)).Where(val => val != null)
.Select(val => val.ToString())
.ToList();
which gives you the list you are looking for.

According to your question
Basically, I am interested in finding out if a simple bool variable is true OR if a Nullable variable is not null.
to tell if a simple boolVariable is true
if(boolVariable){
//bool variable, not nullable
}
to tell if your nullableVariable is not null
if(nullableVariable.HasValue){
//a nullable variable is not null
}
to tell if nullable bool variable is true or/and not null, use the ?? operator
if(variable??false){
//then I'm sure that this is not null and has value=true
}
So in definitive you can use the following code for both nullable bool and bool variables
if(variables!=null &&variables!=false){/*This may give a warning message but it works*/}
or
if(((bool?)variable)??false){
/*variable is not null and is true*/
}

This is a response to the initial question - ignore this.
When you "box" a nullable value (so you put it in an object), it is transformed in its underlying type (bool in your case) or in null... So if you have
bool? value = true;
object value2 = value;
now value2.GetType() == typeof(bool)

Try this
List<string> values = typeof(InstViewModel).GetProperties()
.Select(prop => new { N = prop.Name, T = prop.PropertyType, V = prop.GetValue(ivm, null) })
.Where(prop => prop.N != "SubCollection" && prop.N != "ID" && prop.N != "Name" && prop.N != "Level")
.Where(val => (val.V != null && val.T.IsAssignableFrom(typeof(Nullable<bool>))) || Convert.ToBoolean(val.V))
.Select(val => val.V.ToString())
.Where(str => str.Length > 0)
.ToList();

Try this:
((bool?)val).HasValue
This will return true, if val is a bool or if val is a bool? which value is not null.
On the other hand,
!((bool?)val).HasValue
will only return true if val is bool? and its value is null.
Will not that test suffice in your case?

Related

null check nested objects before using SelectMany

I have list of Countries and inside it have list of Places.
// ...
public IList<ICountriesDTO> Countries { get; set; }
public class CountriesDTO: ICountriesDTO
{
public IEnumerable<IPlacesDTO> Places { get; set;
}
I am trying to get list of Places that are not null.
allPlacesDTO.World.Countries
.SelectMany(x => x.Places == null ? null : x.Places)
.ToList();
But I receive a null exception when Places are null for their Countries object.
How can I do a null check for Places and just use return statement instead of doing select to null object, similar to what I have below?
if (allPlacesDTO.World.Countries.Places == null)
{
return;
}
Update:
My requirement was if there is no places in any of the countries just use the return statement to exit the current function without proceeding further. That was achieved by the accepted answer and Count function.
var lstAllPlaces = allPlacesDTO.World.Countries
.Where(x => x.Places != null)
.SelectMany(x => x.Places)
.ToList();
if (lstAllPlaces.Count() == 0)
{
return;
}
You can do the condition in where clause
allPlacesDTO.World.Countries.Where(x => x.Places != null)
.SelectMany(x => x.Places).ToList();
Or change the ternary operator to return new List() (it can be greedy)

Query different columns depending on generic type argument

I have a table with configurations and there are multiple types (stored in different columns) and i need to query with entity framework for the current type based on the generic type
I have 2 approaches 1 is just casting everything to (dynamic), basically saying i don't need type checking here
and it look like this
static TValue GetValueBasedOnType<TValue>(int configKey)
{
var query = dbcontext.Configurations.Where(c => c.configKey == configKey);
if(typeof(TValue) == typeof(bool))
return (dynamic)(query.Select(c => c.ValueBit).FirstOrDefault() ?? false);
if(typeof(TValue) == typeof(string))
return (dynamic)(query.Select(c => c.ValueText).FirstOrDefault());
if (typeof(TValue) == typeof(decimal))
return (dynamic)(query.Select(c => c.ValueDecimal).FirstOrDefault());
return default(TValue);
}
Or i can just cast the query to the current type, by first making it a general object and then change it back to the original type, like this
static TValue GetValueBasedOnType<TValue>(int configKey)
{
var query = dbcontext.Configurations.Where(c => c.configKey == configKey);
if (typeof(TValue) == typeof(bool))
return (TValue)(object)(query.Select(c => c.ValueBit).FirstOrDefault() ?? false);
if (typeof(TValue) == typeof(string))
return (TValue)(object)(query.Select(c => c.ValueText).FirstOrDefault());
if (typeof(TValue) == typeof(decimal))
return (TValue)(object)(query.Select(c => c.ValueDecimal).FirstOrDefault());
return default(TValue);
}
I just wonder what option is a better idea to use?
You can cast directly to TValue using the Linq Cast function:
static TValue GetValueBasedOnType<TValue>(int configKey)
{
var query = new List<Configuration>{ new Configuration { ValueDecimal = 1.2M, ValueBit = true, ValueText = "Text" }};
if (typeof(TValue) == typeof(bool))
return query.Select(c => c.ValueBit).Cast<TValue>().FirstOrDefault();
if (typeof(TValue) == typeof(string))
return query.Select(c => c.ValueText).Cast<TValue>().FirstOrDefault();
if (typeof(TValue) == typeof(decimal))
return query.Select(c => c.ValueDecimal).Cast<TValue>().FirstOrDefault();
return default(TValue);
}
As you can see, I used a List<Configuration> to test your function. With the following additional code in LinqPad:
public class Configuration
{
public bool ValueBit { get; set; }
public string ValueText { get; set; }
public decimal ValueDecimal { get; set; }
}
void Main()
{
GetValueBasedOnType<bool>(0).Dump();
GetValueBasedOnType<string>(0).Dump();
GetValueBasedOnType<decimal>(0).Dump();
}
my output is, as expected:
True
Text
1.2
Out of interest I ran a similar query against a database of my own in Linqpad and again I got the expected result and the SQL generated was satisfactory - a TOP(1) query.

How can I get an item from a generic list based on two conditions?

I have a generic list of a custom type, of which I'm trying to get back one type instance. I've tried both "FirstOrDefault" and "Where" using the two conditions which need to be true, but both of them give me the same err msg ("Operator '&&' cannot be applied to operands of type 'lambda expression' and 'lambda expression'")
Here they are:
// FirstOrDefault
UnitItemCodeItemID uicii =
unitItemCodeItemIDList
.FirstOrDefault((u => u.Unit == _unit) && (d => d.Description == desc));
// Where
UnitItemCodeItemID uicii =
unitItemCodeItemIDList
.Where((u => u.Unit == _unit) && (d => d.Description == desc));
I don't know if it's pertinent, but the class is:
public class UnitItemCodeItemID
{
public string Unit { get; set; }
public string Description { get; set; }
public string ItemCode { get; set; }
public int ItemID { get; set; }
}
You have to provide just ONE lambda:
UnitItemCodeItemID uicii = unitItemCodeItemIDList
.FirstOrDefault(obj => obj.Unit == _unit && obj.Description == desc);
Think about it this way: it's exactly like writing a foreach loop in a function. Like so:
public UnitItemCodeItemID ExtractFirst(IEnumerable<UnitItemCodeItemID> unitItemCodeItemIDList)
{
foreach(var obj in unitItemCodeItemIDList)
{
if (obj.Unit == _unit && obj.Description == desc)
return obj;
}
return null;
}
Your lamba must provide the "if" part, the rest is in the Linq implementation.
You need to provide a single lambda expression that encapsulates both conditions
.Where(p => p.Unit == _unit && p.Description == desc);
Your previous attempt was trying to combine two separate lambda expressions with an and statement.

C# - Getting all enums value by attribute

I have this following enum :
public enum KodEnum
{
[EnumType(EnumType = "Task")]
TaskTab,
[EnumType(EnumType = "Task")]
TaskReason,
[EnumType(EnumType = "Action")]
ActionTab,
[EnumType(EnumType = "Action")]
ActionReason
}
public class EnumTypeAttribute : Attribute
{
public string EnumType { get; set; }
}
And I want to get a list of all the enums that have the EnumType of "Task".
How could I do that?
Something like this should get you on the way...
var enumValues = (from member in typeof(KodEnum).GetFields()
let att = member.GetCustomAttributes(false)
.OfType<EnumTypeAttribute>()
.FirstOrDefault()
where att != null && att.EnumType == "Task"
select member.GetValue(null))
.Cast<KodEnum>()
.ToList();
If you want the int value, then just cast it:
var enumValues = (from member in typeof(KodEnum).GetFields()
let att = member.GetCustomAttributes(false)
.OfType<EnumTypeAttribute>()
.FirstOrDefault()
where att != null && att.EnumType == "Task"
select (int)member.GetValue(null))
.ToList();
And all-lambda solution:
var enumValues = typeof(KodEnum)
.GetFields()
.Select(x => new
{
att = x.GetCustomAttributes(false)
.OfType<EnumTypeAttribute>()
.FirstOrDefault(),
member = x
})
.Where(x => x.att != null && x.att.EnumType == "Task")
.Select(x => (int)x.member.GetValue(null))
.ToList();
You can do it like:
var result = Enum.GetValues(typeof(KodEnum)).OfType<KodEnum>()
.Where(x=>x.EnumType() == "Task");
here is EnumType extension method implementation:
public static class EnumExtensions
{
public static string EnumType(this Enum value)
{
FieldInfo field = value.GetType().GetField(value.ToString());
EnumTypeAttribute attribute
= Attribute.GetCustomAttribute(field, typeof(EnumTypeAttribute ))
as EnumTypeAttribute;
return attribute == null ? value.ToString() : attribute.EnumType ;
}
}
Keyword is Reflection:
Have you tried something like this?
Enum.GetValues(typeof(KodEnum))
.OfType<KodEnum>()
.Where(o => o.GetType()
.GetCustomAttributes(typeof(EnumTypeAttribute), false)
.OfType<EnumTypeAttribute>()
.FirstOrDefault()
.EnumType == "Task");

How to check all properties of an object whether null or empty?

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();

Categories

Resources