I have some code that reads data from Excel sheets & put to List.
Now here comes a scenario that user copy some valid data then leaves a lot of rows empty & again then copy valid data. This reads a lot of empty rows. I am using some old code for excel read & that might be used somewhere else so I don't wish to mess up with that.
The problem is I have a lot of object inside List that are initialised but all values are null. So I ended up checking all attribuets in if like:
if (lstConsolidatedData != null)
{
foreach (var lst in lstConsolidatedData)
{
if(lst.a!=null && lst.b!=null && lst.c!=null //& so on....)
{
//some stuff...
}
}
}
I know this is not wither best or maintainable way since excel sheets can be modified & thus whole columns list code need to be changed again & again for a single column added or removed from excel.
Is there any way to check all values inside lst for null in a single statement?
some thing like lst.all !=null
Any idea if not code will also work for me.
Please note lst==null is false
EDIT: using answers from below I am getting this error
EDIT:
o.GetType().GetProperties().Any(c => c.GetValue(o) == null) works for any null but What I actually want to delete rows which contains no data in all columns not for particular one or two column. Issue is not resolved by o.Item1 != null && ... also since name/number of columns changes frequently.
You can use reflection to do this, but beware that it carries performance losses over doing it explicitly.
public bool IsAnyPropertyNull(object o)
{
return o.GetType().GetProperties().Any(c => c.GetValue(o) == null);
}
There is, however, no built-in expression to reduce the o.Item1 != null && o.Item2 != null && ... type syntax.
Also, I'm assuming the values you're talking about are properties. You could also use GetFields or whatever you need if that's more appropriate.
As Mathew Huagen pointed out using reflection to get properties and then checking their values seems to be fine. However, this has a big caveat that is there may be some properties you don't want to be checked. To solve this,you can either put them inside a list (as Tim Schmelter mentioned), or you can decorate desired properties of ConsolidatedData with a custom attribute to distinguish them:
public class ConsolidatedData
{
public int Id { get; set; }
[NotNull]
public object PropertyOne { get; set; }
[NotNull]
public object PropertyTwo { get; set; }
}
public class NotNull : Attribute { }
Then checking against null is safe when you filter out the properties not having NotNull attribute:
ConsolidatedData v = new ConsolidatedData();
bool allNotNull = v.GetType().GetProperties()
.Where(p => null != (Attribute.GetCustomAttribute(p, typeof(NotNull)) as NotNull))
.All(p=>p.GetValue(v) !=null );
Here property Id is not get checked.
You could write an extension method for your ConsolidatedData like this;
public static bool IsAnyPropNull(this ConsolidatedData cdata)
{
return cdata.GetType().GetProperties().Any(p => p.GetValue(this) == null);
}
And you could then filter your list with a one-liner;
var filteredList = lstConsolidatedData.Where(cd => !cd.IsAnyPropNull()).ToList();
This will return a list of all object without nulls. If you want the nulls, remove the !, ofcourse.
Edit;
Wow, my answer is almost the same as Matthew Haugen's... both should work fine, even though the implementation is slightly different.
I ended up digging down into old code & before turning dataset into List I deleted empty rows using code:
//Deleting empty records from Datset
foreach (DataTable source in result.Tables)
{
for (int i = 0; i < source.Rows.Count; i++)
{
DataRow currentRow = source.Rows[i];
bool isEmpty = false;
foreach (var colValue in currentRow.ItemArray)
{
if (!string.IsNullOrEmpty(colValue.ToString()))
{
isEmpty = false;
break;
}
else
isEmpty = true;
}
if (isEmpty)
source.Rows[i].Delete();
}
}
result.AcceptChanges();
Don't forget .AcceptChanges() since it actually save the changes done to dataset without which no records are removed.
Related
Well, I need to repeat same code for many properties.
I've seen examples taking Action delegates, but they don't fit quite well here.
I want something like this: (see explanation below)
Dictionary<Property, object> PropertyCorrectValues;
public bool CheckValue(Property P) { return P.Value == PropertyCorrectValues[P]; }
public void DoCorrection(Property P) { P.Value = PropertyCorrectValues[P]; }
.
I want to have a dictionary containing many properties and their respective "correct" values. (I know it's not well declared, but that's the idea). Properties are not necessarely inside my class, some of them are in objects of different assemblies.
A method bool CheckValue(Property). This method must access the actual value of the property and compare to the correct value.
And a method a void DoCorrection(Property). This one sets the property value to the correct value.
Remember I have many of those properties, I wouldn't like to call the methods by hand for each property. I'd rather iterate through the dicionary in a foreach statement.
So, the main question is in the title.
I've tried the by ref, but properties don't accept that.
Am I obligated to use reflection??? Or is there another option (if I need, reflection answer will be accepted as well).
Is there anyway I can make a dictionary with pointers in C#? Or some kind of assignment that changes the value of variable's target instead of changing the target to another value?
Thanks for the help.
You can do this using reflection. Get a list of the properties on the object of interest with typeof(Foo).GetProperties(). Your PropertyCorrectValues property can have type IDictionary<PropertyInfo, object>. Then use the GetValue and SetValue methods on PropertyInfo to perform the desired operations:
public bool CheckProperty(object myObjectToBeChecked, PropertyInfo p)
{
return p.GetValue(myObjectToBeChecked, null).Equals(PropertyCorrectValues[p]);
}
public void DoCorrection(object myObjectToBeCorrected, PropertyInfo p)
{
p.SetValue(myObjectToBeCorrected, PropertyCorrectValues[p]);
}
In addition to Ben's code I'd like to contribute the following code fragment:
Dictionary<string,object> PropertyCorrectValues = new Dictionary<string,object>();
PropertyCorrectValues["UserName"] = "Pete"; // propertyName
PropertyCorrectValues["SomeClass.AccountData"] = "XYZ"; // className.propertyName
public void CheckAndCorrectProperties(object obj) {
if (obj == null) { return; }
// find all properties for given object that need to be checked
var checkableProps = from props
in obj.GetType().GetProperties()
from corr in PropertyCorrectValues
where (corr.Key.Contains(".") == false && props.Name == corr.Key) // propertyName
|| (corr.Key.Contains(".") == true && corr.Key.StartsWith(props.DeclaringType.Name + ".") && corr.Key.EndsWith("." + props.Name)) // className.propertyName
select new { Property = props, Key = corr.Key };
foreach (var pInfo in checkableProps) {
object propValue = pInfo.Property.GetValue(obj, null);
object expectedValue = PropertyCorrectValues[pInfo.Key];
// checking for equal value
if (((propValue == null) && (expectedValue != null)) || (propValue.Equals(expectedValue) == false)) {
// setting value
pInfo.Property.SetValue(obj, expectedValue, null);
}
}
}
When using this "automatic" value correction you might also consider:
You cannot create a PropertyInfo object just by knowing the property name and independently of the declaring class; that's why I chose string for the key.
When using the same property name in different classes then you might need to change the code that is doing the actual assignment because the type between the correct value and the property type might differ.
Using the same property name in different classes will always perform the same check (see point above), so you might need a syntax for property names to restrict it to a specific class (simple dot notation, doesn't work for namespaces or inner classes, but might be extended to do so)
If needed you can replace the "check" and "assign" part with separate method calls, but it might be done inside the code block as stated in my example code.
I am having a bit following the "a method should only do one thing"
I have a car text file, and if it contains even one BMW I want to set isValid to true, but while I am going through the text file anyways I thought I would also populate two list high end models(M3,M5 etc) and lower model (335, X3 etc).
I know that method should only do one thing, but it seems so convenient for it to also populate the lists. Here is what I have:
private bool hasBMWegments()
{
foreach (ClassLib.CarSegment carElement in CarSegmentFactory.ContainsCar("BMW"))
{
isValid = true;
if (carElement.Class.IndexOfAny(lowerModels) == 0)
{
lstOlderSegment.Add(carElement.ElementNumber);
}
if (carElementClass.IndexOfAny(upperModels) == 0)
{
lstNewerSegment.Add(carElement.ElementNumber);
}
}
return isValid;
}
Should I just create a method that performs the foreach check again? Or should I create another method inside that method (I would think that would be messy, and wouldn't related to the method name)
edit: sorry working with framework 2.0
I find that code to be a mess compared to this:
private IEnumerable<ClassLib.CarSegment>
GetModels(IEnumerable<ClassLib.CarSegment> segments, string modelID)
{
return segments.Where(x => x.Class.IndexOfAny(modelID) == 0);
}
// ...
var bmwSegments = CarSegmentFactory.ContainsCar("BMW").ToArray();
bool isValid = bmwSegments.Any();
var olderModelSegments = GetModels(bmwSegments, lowerModels);
var newerModelSegments = GetModels(bmwSegments, upperModels);
This code is obviously correct at a glance. The other code makes you look twice at the loop to figure out what's going on.
It looks like all you're doing is setting isValid to true on the first pass through the foreach. So all isValid really means is "is there at least one element?".
In which case you do not need to iterate twice. You can use Any() to do the valid check:
bool IsValid(IEnumerable<CarSegment> elements)
{
return elements.Any();
}
void PopulateSegments(IEnumerable<CarSegment> elements)
{
foreach(var element in elements)
{
//add to lists
}
}
I've posted a code sample below. Firstly let me explain
termStore.Groups in the code below is a collection of Group Objects (The exact class is irrelevant).
Checking for null : if (termStore.Groups[groupName] == null) seems like a logical (clean) approach, but if the Groups collection is empty then an exception is produced.
using the termStore.Groups.Contains is not an option either because this expects a strong type i.e: .Contains(Group)... not .Contains(GroupName as string)
Can someone recommend a clean / generic way I can check for if an item exists in collection .
Thank you....
TermStore termStore = session.TermStores.Where(ts => ts.Name == termStoreName).FirstOrDefault();
if (termStore.Groups[groupName] == null)
{
termStore.CreateGroup(groupName);
termStore.CommitAll();
}
Update: The exact class Sharepoint Taxonomy Classes. http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.taxonomy.group.aspx
Update 2, the exact collection : http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.taxonomy.groupcollection.aspx
Microsoft.SharePoint.Taxonomy.GroupCollection implements IEnumerable<Group>, so a bit of LINQ is probably just what the doctor ordered:-
if(termStore.Groups.Any(x => x.Name == "MyGroup"))
{
// group contains at least one item matching the predicate.
}
else
{
// group contains no items matching the predicate.
}
You'll need to be using .NET 3.5 or better and add "using System.Linq;" to the top of your file.
Edit
If you don't have LINQ available, or if it offends you, or if you've genuinely profiled and found that iterating over Groups is killing performance compared to the string indexer, you could use GroupCollection.Count to avoid the error state:-
if (termStore.Groups.Count == 0 || termStore.Groups[groupName] == null)
{
// Group doesn't exist.
}
IEnumerable.Any(...) should work for your case:
termsStore.Groups.Any()
I think this is what you are looking for:
termStore.Groups.ContainsKey(groupName)
Checks that the key exists, doesn't throw an exception if it doesn't. This is assuming that Groups is a collection that implements IDictionary.
May be this
termStore.Any() && termStore.Groups.Any() && termStore.Groups[groupName] == null
Ok, 2nd attempt. If Groups doesn't contain the required ContainsKey method then you can write it yourself. Then you can just use ContainsKey in place of Contains.
static class GroupExtensions
{
public static bool ContainsKey(this Groups groups, string key)
{
try
{
if(groups[key] == null)
{
return false;
}
}
catch
{
return false;
}
return true;
}
}
I have a class property that is a list of strings, List.
Sometimes this property is null or if it has been set but the list is empty then count is 0.
However elsewhere in my code I need to check whether this property is set, so currently my code check whether it's null and count is 0 which seems messy.
if(objectA.folders is null)
{
if(objectA.folders.count == 0)
{
// do something
}
}
Any recommendation on how this should be handled?
Maybe I should always initialise the property so that it's never null?
When I have List as a property, I usually have something that looks like the following (this is not a thread safe piece of code):
public class SomeObject
{
private List<string> _myList = null;
public List<string> MyList
{
get
{
if(_myList == null)
_myList = new List<string>();
return _myList;
}
}
}
Your code would then never have to check for null because the Property would be initialized if used. You would then only have to check for the Count.
Right now your code will Always throw a Null Pointer exception, you are checking for Null and if it IS null - you're trying to access an object which does not exist.
If for your application the collection being a null reference never has a different meaning than the collection being empty, then yes, I would say you should always initialize it and this way remove the null checks from the remaining code.
This approach only makes sense if the property setter does not allow to change it to a null reference after initialization.
You have three options (and you need to decide based on your project):
Create a method to check for NullOrNoElements. Pro: Allows both null and no entries. Con: You have to call it everywhere you want to use the property.
Preinitialize with a list. Pro: Thread-save and very easy. Con: will use memory even when not used (depending on how many instances you have this may be a problem)
Lazy initialize Pro: Does only use memory when really used. Con: NOT thread save.
private List<string> lp = null;
public List<string> ListProp
{
get
{
if(lp == null)
lp = new List<string>();
return lp;
}
}
You could always initialize the property so it's an empty List. Then you can just check the count property.
List<String> Folder = Enumerable.Empty<String>();
I once wrote an extension method for ICollection objects that checked if they were null or empty
public static Boolean IsNullOrEmpty<T>(this ICollection<T> collection)
{
return collection == null ? true : collection.Count() == 0;
}
public static Boolean IsPopulated<T>(this ICollection<T> collection)
{
return collection != null ? collection.Count() > 0 : false;
}
You could do this in a single IF
if(objectA.folders is null || objectA.folders.count == 0)
Or you could create a boolean property in the class which checks this status for you and returns a result
public bool objectA.FolderIsNullOrEmpty
{
get { return objectA.folders is null || objectA.folders.count == 0;}
}
If it does not make a difference to your application, I would rather recomend initializing the List to start with.
You could handle this by initializing the object in the constructor. This is usually where this type of thing is done. Although I see nothing wrong with your current code. No point in initializing stuff that doesn't exist yet, it just wastes memory.
Its a good question. I would add a method to objectA FoldersNullOrEmpty() that you can use eg
public virtual FoldersNullOrEmpty()
{
return (folders == null || folders.count == 0)
}
I almost always initialize lists and even make sure they can't be set to null if exposed by any setters. This makes using them much easier.
I am doing some simple sanity validation on various types. The current test I'm working on is checking to make sure their properties are populated. In this case, populated is defined as not null, having a length greater than zero (if a string), or not equal to 0 (if an integer).
The "tricky" part of this test is that some properties are immune to this check. Right now I use a giant if statement that weeds out properties that don't need to be checked.
//Gets all the properties of the currect feature.
System.Reflection.PropertyInfo[] pi = t.GetProperties();
for(int i = 0; i < pi.Length; i++)
{
if(!pi[i].Name.Equals("PropertyOne")
&& !pi[i].Name.Equals("PropertyTwo")
&& !pi[i].Name.Equals("PropertyThree")
//... repeat a bunch more times
&& !pi[i].Name.IndexOf("ValueOne") != -1
&& !pi[i].Name.IndexOf("ValueTwo") != -1
//... repeat a bunch more times
{
//Perform the validation check.
}
}
When profiling, I noticed the if statement is actually performing worse than the reflection (not that the reflection is blazing fast). Is there a more efficient way to filter the properties of several different types?
I've thought about a massive regular expression but I'm unsure on how to format it, plus it would probably be unreadable given its size. I've also considered storing the values in a List and then using Linq but I'm not sure how to handle the cases that use String.IndexOf() to find if the property contains a certain value.
Thanks in advance.
Make a HashSet "exactNames" with PropertyOne, PropertyTwo etc, and then a List "partialNames" with ValueOne, ValueTwo etc. Then:
var matchingProperties = pi.Where(exactNames.Contains(pi.Name) ||
partialNames.Any(name => pi.Name.Contains(name));
foreach (PropertyInfo property in matchingProperties)
{
// Stuff
}
(Odd indenting just to avoid wrapping.)
Note that you could cache the set of properties to validate on a per-type basis, so you only need to go through this check once per type.
Your idea help speed up my program, thank you. However, you had some syntax issues, plus you were matching items found in the lists and I needed items not in the list. Here is the code I ended up using.
List<System.Reflection.PropertyInfo> pi = type.GetProperties().ToList();
var matchingProperties = pi.Where( prop => !PropertyExclusionSet.Contains( prop.Name )
&& !PropertiesPartialSet.Any( name => prop.Name.Contains( name ) ) );
You might consider decorating your properties with attributes that tell what action needs to be done to them.
public class MyClass {
[CheckMe]
public int PropertyOne { get; set; }
[DontCheckMe]
public int PropertyTwo { get; set; }
}