Check if item of List<T> is valid - c#

I am porting a small program of mine from Typescript to C#. In the original program I had a lot of checks like this:
var array: T[] = [];
if (!array[1234]) { // do something }
which basically checks if 1234 is a wrong index (undefined) or if the item has been specifically set to null or false by me.
Now when porting this to C# I'm basically replacing T[] with List<T> but I don't know what is the quickest way to perform this check, since if I use an invalid index I get an exception.
So my question is, what is the best way to check for both invalid index and index of a null or false item?

To check if the requested index is within the bounds you need to check myIndex < myList.Count.
If T is bool, you can do !myList[ix] like you are already doing.
In .NET, since bool is not nullable, you do not need to check if it is null. However, if T is nullable or a Nullable<T> i.e. bool?, you still need to do the == null check and also check if it isn't false.
If you are working in .NET 3.5 or above, you can write an extension method to make this a little easier on you. Here is something I whipped up to handle almost all cases (maybe all?).
public static class ListExtensions
{
public static bool ElementIsDefined<T>(this List<T> list, int index)
{
if (index < 0 || index >= list.Count)
return false;
var element = list[index];
var type = typeof (T);
if (Nullable.GetUnderlyingType(type) != null)
{
if (element is bool?)
return (element as bool?).Value;
return element != null;
}
var defaultValue = default(T);
// Use default(T) to actually get a value to check against.
// Using the below line to create the default when T is "object"
// causes a false positive to be returned.
return !EqualityComparer<T>.Default.Equals(element, defaultValue);
}
}
Quick overview of what this does:
Checks if the index is within the bounds.
Checks if the Type is Nullable (bool?, int?, etc.)
If it is, then we have to double check if the type is bool? so we can correctly determine if false was supplied and return based on that.
Then determines if the actual value out of the array is the default value. If it's bool, default is false, int is 0, and any references types are null.
You can call it like this:
var listBool = new List<bool?>();
listBool.Add(true);
listBool.Add(false);
listBool.Add(null);
listBool.ElementIsDefined(0) // returns true
listBool.ElementIsDefined(1) // returns false
listBool.ElementIsDefined(2) // returns false
Now quick note, this is not going to be lightning fast. It can be split up to handle different types of List<T> objects though so you can remove or add logic based on if you needed to create a similar method for List<int> or List<MyClass> and so on, but because I defined it as using a List<T> this method will show up for all Lists.

Now that you're using C# and have access to the BCL, you should use a Dictionary for this kind of thing. This allows you to efficiently add indices and check whether they're present.
For example, assuming T was string:
var s = new Dictionary<int, string>();
s[1234] = "Hello";
s[9999] = "Invalid";
var firstIndexCheck = s.ContainsKey(1234) && s[1234] != "Invalid"; // true
var secondIndexCheck = s.ContainsKey(9999) && s[9999] != "Invalid"; // false

For checking correct index just check that it is less then array/list size.
int index = 1234;
List<T> list = new List<T>();
if (index < list.Count) {
}
For checking for null combine index checking and null checking:
index < list.Count && list[index] != null
(in case if you have array of reference types)

Related

Validate null object

In order to validate if model comes null or not I use something like this:
if (model is null || !model.Any()) return this;
But in latest Microsoft conference I saw guys use something like:
if(model is { })
I try to use it but always return true (if object comes null or not)
So my question is. Is there a new way to check if a model comes null?
What is the correct usage of brackets { }
Note: I googled about that brackets but I found anything. Regards
You can do a generic extension method to check if your object is null or not.
Try:
public static bool IsNullOrEmpty<T>(this IEnumerable<T> source) {
return source?.Any() != true;
}
Another way to check for NullOrEmpty is to coerce Count() to an int?. Then we can compare the result of GetValueOrDefault to 0:
if((model?.Count).GetValueOrDefault() == 0) return this;
How it works:
Because the ?. operator will return null if the left side is null, and Count returns an int, the result of (model?.Count) is a Nullable<int>.
The GetValueOrDefault method returns the value of Count if model is not null, otherwise it returns default(int) (which is 0).
This way if model is null, the condition returns 0

what does the questionmark do when typing object?.field? [duplicate]

With C# 6.0 in the VS2015 preview we have a new operator, ?., which can be used like this:
public class A {
string PropertyOfA { get; set; }
}
...
var a = new A();
var foo = "bar";
if(a?.PropertyOfA != foo) {
//somecode
}
What exactly does it do?
It's the null conditional operator. It basically means:
"Evaluate the first operand; if that's null, stop, with a result of null. Otherwise, evaluate the second operand (as a member access of the first operand)."
In your example, the point is that if a is null, then a?.PropertyOfA will evaluate to null rather than throwing an exception - it will then compare that null reference with foo (using string's == overload), find they're not equal and execution will go into the body of the if statement.
In other words, it's like this:
string bar = (a == null ? null : a.PropertyOfA);
if (bar != foo)
{
...
}
... except that a is only evaluated once.
Note that this can change the type of the expression, too. For example, consider FileInfo.Length. That's a property of type long, but if you use it with the null conditional operator, you end up with an expression of type long?:
FileInfo fi = ...; // fi could be null
long? length = fi?.Length; // If fi is null, length will be null
It can be very useful when flattening a hierarchy and/or mapping objects. Instead of:
if (Model.Model2 == null
|| Model.Model2.Model3 == null
|| Model.Model2.Model3.Model4 == null
|| Model.Model2.Model3.Model4.Name == null)
{
mapped.Name = "N/A"
}
else
{
mapped.Name = Model.Model2.Model3.Model4.Name;
}
It can be written like (same logic as above)
mapped.Name = Model.Model2?.Model3?.Model4?.Name ?? "N/A";
DotNetFiddle.Net Working Example.
(the ?? or null-coalescing operator is different than the ? or null conditional operator).
It can also be used out side of assignment operators with Action. Instead of
Action<TValue> myAction = null;
if (myAction != null)
{
myAction(TValue);
}
It can be simplified to:
myAction?.Invoke(TValue);
DotNetFiddle Example:
using System;
public class Program
{
public static void Main()
{
Action<string> consoleWrite = null;
consoleWrite?.Invoke("Test 1");
consoleWrite = (s) => Console.WriteLine(s);
consoleWrite?.Invoke("Test 2");
}
}
Result:
Test 2
Basically, I have applied ?. operator after Model as well. I am trying to know that whether it can be applied directly to the model or does it only work with the navigation properties?
The ? or null conditional operator operators on the left value, regardless of the type of value. And the compiler doesn't care what the value is on the right. It's simple compiler magic (meaning it does something you can already do, just in a simplified why).
For example
var a = model?.Value;
is the same as saying
var a = model == null ? null : model.Value;
In the second case the evaluation of checking for null has no associate with the value returned. The null conditional operator basically just always return null if the left value is null.
The type of member (Method, Field, Property, Constructor) .Value is irrelevant.
The reason your DotNetFiddle example doesn't work is because the compiler being use for the .Net 4.7.2 isn't compatible with the c# version that support the null conditional operator. Changing it to .Net 5, works:
https://dotnetfiddle.net/7EWoO5
This is relatively new to C# which makes it easy for us to call the functions with respect to the null or non-null values in method chaining.
old way to achieve the same thing was:
var functionCaller = this.member;
if (functionCaller!= null)
functionCaller.someFunction(var someParam);
and now it has been made much easier with just:
member?.someFunction(var someParam);
I strongly recommend this doc page.

Return null to avoid unknown exceptions from a method in C#

I have the following method that opens a Excel workbook and returns it to be used in another method.
private Excel.Workbook openWorkbook()
{
// Get excel file path returns the file path of the excel workbook if it exists, otherwise returns null.
List<string> filePaths = getExcelFilePath();
if (filePaths != null)
{
return excel.Workbooks.Open(filePaths[0]);
}
return null;
}
As you can see, I'm returning null to avoid a try-catch for a non-exixtent workbook when I call this from another method. Is it bad practice to do this. I do a similar thing in the following method which is supposed to return a list:
private List<string> getSOsToDelete()
{
// rawData is private variable in the class. If the workbook was not open this worksheet is set to null in another method similar to openWorkbook() above.
if (rawData != null)
{
List<string> ToDeleteSOs = new List<string>();
for (int i = rawData.Cells.SpecialCells(Excel.XlCellType.xlCellTypeLastCell, Type.Missing).Row; i > 1; i--)
{
if (rawData.Cells[i, 7].Value2.ToString() != "B2B" || rawData.Cells[i, 7].Value2.ToString() != "" || rawData.Cells[i, 8].Value2.ToString() != "Trns-Inc" || rawData.Cells[i, 8].Value2.ToString() != "")
{
string SONumber = rawData.Cells[i, 3].Value2.ToString();
ToDeleteSOs.Add(SONumber);
}
}
return ToDeleteSOs;
}
return null;
}
If not so, what is the best way to write methods like these? For part 2 I guess I could return an empty list and check for length. I'm not sure which is better. However, for first method, I'm really not sure what to return if the file doesn't exist.
I think there is no hard and fast rule for this. But I would return null from first method as returning a null where there is no workbook seems meaning full as null represent no object but from second method empty list would be a batter option as with list we used to use Count before using it instead of null or iterate over list etc. This also goes with convention like ToList will return list of zero elements instead of returning null.
Return null to avoid unknown exceptions from a method in C#
There could be different way to tell the caller method that error occurred in called method and exception is one of those and widely adopted. You can document the method to tell when kind of exception are expected from the method. Lets look at documentation of String.Substring Method (Int32, Int32) on MSDN. The documentation mentions that this method could through ArgumentOutOfRangeException when startIndex plus length indicates a position not within this instance, or startIndex or length is less than zero, MSDN

efficient way to check for changes in a "calculation" class

I have the following "calculation" class.
public class Foo
{
private int? _sum = 0;
public int Sum
{
get
{
if (_sum == null)
_sum = 1 + 1; //simple code to show "some" calculation happens...
return _sum.GetValueOrDefault();
}
}
}
In this example there is only 1 Field/Member but in my real class there are around 50 Members, that all look similar just with different value calculations.
In the class I also have a Recalc method.
This Recalc method does 4 things
Save the old values
set all fields to null
calls the getter of every member
Checks if the old values differ from the newvalues and does related stuff
I am not sure whats the best way to store the old values and check for changes with the new values.
My current implementation is this:
public string GetValuesKey()
{
//again this method only handles the 1 Member and not all 50 in real app its string.Format("{0}|{1}|{2}|...{49}|{50}|", ....);
return string.Format("{0}|", this.Sum);
}
public void Recalc()
{
var oldValues = GetValuesKey();
//set all fields to null
//call the getters
var newValues = GetValuesKey();
if (oldValues != newValues)
{
//something changed...
}
}
But with this code there is a memory/performance issue since I am doing boxing with the struct (decimal) writing to a reference type (string).
I kind of want to prevent doing 50 additional fields (something like _oldSum) for all the members.
I just need to check if any member has changed during the Recalc procedure.
Just in Case, I cannot do the following code.
public void Recalc()
{
var changes = false;
var oldValue = this.Sum;
_sum = null;
var newValue = this.Sum;
if (oldValue != newValue)
changes = true;
//check next member
oldValue = this.Sum2;
_sum2 = null;
newValue = this.Sum2;
if (oldValue != newValue)
changes = true;
//check next member and so on...
}
Since I need to set all fields to null first and only AFTER all of them have been set to null I can execute the getters, since the members are dependant on each other for exmple if the Sum Member would aggregate two other members and they havent been set to null first they would still have old values.
So I need a way to store something that represents all values before setting the fields null and after calling the getter of the members a way to check for changes.
Any help is welcome.
Edit:
Here is the code, I wrote to test performance/memory:
http://pastebin.com/3WiNJHyS
Instead of combining all values in a string and have some pefomance hit on that string construction - put all values in array (of decimal), then set all fields to null, make your calculation and compare arrays of old and new values.
If you don't want to write yourself all the 50 _oldValue fields, the only alternative is to use Reflection, that implies some boxing/unboxing, so performance will not be the best possible.
Anyway, in the following implementation I assume that in the Foo class the members that are involved in the calculation are all and the only ones that are properties of type decimal?.
Otherwise, we need a more complicated solution, with BindingFlags, and/or Attribute on every field/property involved, and so on.
public void Recalc()
{
var propertyInfos = GetType()
.GetProperties()
.Where(pInfo => pInfo.PropertyType.IsValueType);
var fieldInfos = GetType()
.GetFields()
.Where(fInfo => fInfo.FieldType.IsValueType);
//create a dictionary with all the old values
//obtained from the backing fields.
var oldValueDictionary = fieldInfos.ToDictionary(
fInfo => fInfo.Name,
fInfo => (decimal?)fInfo.GetValue(this));
//set all properties to null
foreach (var pInfo in propertyInfos)
pInfo.SetValue(this, null);
//call all the getters to calculate the new values
foreach (var pInfo in propertyInfos)
pInfo.GetValue(this);
//compare new field values with the old ones stored in the dictionary;
//if only one different is found, the if is entered.
if (fieldInfos.Any(fInfo =>
(decimal?)fInfo.GetValue(this) != oldValueDictionary[fInfo.Name]))
{
//do stuffs
}
}
As a final note, your class configuration is very strange. Are you sure that setting all the calculations in the getters is the best choice? Maybe you should re-think about you design. One task is to retrieve a property value (a getter), another task is to calculate something (starting from some value stored in the backing fields)...

Check if a method can be invoked with the array of parameters

I'm invoking a method using reflection but i want to check that the array of parameters i have are of the correct type before doing so. I've tried several methods like Type.IsAssignableFrom and other comparisons, but they still give false positives. For example when using an int as parameter to a function that accepts an enum.
The reference source seems to do exactly this check, is this exposed somewhere?
My current code looks like this:
private bool CheckTypeMatch(ParameterInfo[] methodParameters, Type[] callParameterTypes)
{
if (methodParameters.Length < callParameterTypes.Length)
{
return false;
}
for (int index = 0; index < callParameterTypes.Length; index++)
{
Type type = methodParameters[index].ParameterType;
if (callParameterTypes[index] != null && !type.IsAssignableFrom(callParameterTypes[index]) && !(type.IsEnum && System.Enum.GetUnderlyingType(type).IsAssignableFrom(callParameterTypes[index])))
{
return false;
}
}
return true;
}
I am worried there are more cases where the type of the parameter is actually compatible with the method but is being rejected by this function.
Thanks in advance!

Categories