C# - finding first enum in IEnumerable and casting to string - c#

I'm working in JetBrains Rider and have ran into a warning that keeps appearing. Consider this situation:
public enum ValueEnum {
A,B,C
}
public class Value {
public ValueEnum ValueEnum { get; set; }
}
public class ValueWrapper {
public IEnumerable<Value> Values { get; set; }
}
I'm trying to obtain the first enum in the list and convert it into a string. This code works fine:
var format = string.Empty;
if (alert.Values != null && alert.Values.Count > 0)
{
var template = alert.Values.First();
format = nameof(template.ValueEnum);
}
However I'm getting the Value assigned is not used in any execution path warning. Converting the above snippet into the following:
var format2 = string.Empty;
if (alert.Values != null)
{
foreach (var template in alert.Values)
{
format2 = nameof(template.ValueEnum);
break;
}
}
Yields a Local variable "template" is only used to capture its name.
Is there a cleaner way to write this (using LINQ or whatnot) to be in line with c# best practices?

Assuming you actually want the string value of the enum, and not the literal string "ValueEnum", try:
alert.Values?.FirstOrDefault()?.ValueEnum.ToString() ?? string.Empty;
(Both of your approaches would have worked, had you changed nameof(template.ValueEnum) to template.ValueEnum.ToString(), but they are unnecessarily verbose).

Related

C# Class Object JavaScript like use

In C# I have a class object defined like:
public class Row
{
public string id { get; set; }
public string full_name { get; set; }
public string email { get; set; }
}
Next I can use it like:
Row row = new Row();
And then do something like this to set a value:
row.id = "id123";
How do I make some type of "dynamic" reference? This doesn't work:
string col = "id";
row[col] = "id123";
You can use Reflection in C# like this:
var prop=row.GetType().GetProperty("id");
prop.SetValue(row,"id123");
To answer your exact question, you could create a custom indexer:
public object this[string key]
{
get
{
switch(key)
{
case nameof(id): return id;
case nameof(full_name): return full_name;
case nameof(email): return email;
default: throw new ArgumentOutOfRangeException();
}
}
set
{
switch(key)
{
case nameof(id):
id = value.ToString();
break;
case nameof(full_name):
full_name = value.ToString();
break;
case nameof(email):
email = value.ToString();
break;
default: throw new ArgumentOutOfRangeException();
}
}
}
public void Foo()
{
var row = new Row();
row["id"] = "Foo";
}
Or you use reflection as TSungur has answered:
public object this[string key]
{
get
{
var prop = GetType().GetProperty(key);
return prop.GetValue(this);
}
set
{
var prop = GetType().GetProperty(key);
prop.SetValue(this, value);
}
}
However, If I were you, I would review your current library design. Probably you want to use an ORM like Entity Framework, which does all the mapping for you.
C# is a strongly typed language. This means that once a type is defined, you can't changed it dynamically during run time*. You also can't access the properties of an object with [] like in JavaScript. Therefore you can't achieve what you are looking for in C#. C# way would most likely be to access the id property directly through row.id = "id23";. In C# you always know during compile time what properties and methods are available on an object. If you need more flexibility what properties will be there, you can also use a Dictionary, KeyValuePair or simply a List.
*There is actually a dynamic key word that gives you some of that functionality - but it's uncommon to use that all over the place. Coming from JavaScript I would recommend to forget about it for the moment. There is almost always an other, "more C#-like" way.

c# how to check if queue contains object property with a specific value?

I want to get Boolean value if queue contains object having particular value in the properties.
e.g)
public class Order
{
public string orderType { get; set; }
public string sCode { get; set; }
public int iNum { get; set; }
...omit...
}
Queue<Order> queueSendOrder = new Queue<Order>();
Then, how to check if Queue contains or not if contains any object having sCode="Code1", iNum=1?
Thank you.
Using the Linq Any() extension method, this is quite simple:
var containsCode1 = queueSendOrder.Any(o => o.sCode == "Code1");
var containsNum1 = queueSendOrder.Any(o => o.iNum == 1);
Or both:
var containsCode1AndNum1 = queueSendOrder.Any(o =>
o.sCode == "Code1"
&& o.iNum == 1);
Side note: It's considered bad practice these days to use Hungarian notation to denote types. So sCode should really just be Code and iNum would be Num (though I would choose a better name than that)

C# get if a property is any sort of list

I'm trying to make a text writer according to my classes properties in the following pattern:
MyClass
ID 1
Name MyName
AnotherProperty SomeValue
ThisIsAnotherClass
AnotherClassProperties 1
//Example class
public class MyClass
{
public int ID { get; set; }
public string Name { get; set; }
public string AnotherProperty { get; set; }
public AnotherClass ThisIsAnotherClass { get; set; }
}
So I'm taking each property name, writing it, a blank space, then it's value (if there is any).
Now I'm trying to implement support for lists and anything array-like for something like this:
MyClass
ArrayTest
1
2
3
If it's a class, I'll have a recursive for the function so I can display all values inside the list/array in this pattern. (it's for a webservice)
My question is, how can I find if a specific property is something list-able?
I've tried:
Type type = myObject.GetType();
PropertyInfo[] properties = type.GetProperties();
for(int i = 0; i < properties.Length; i++)
{
if(properties[i].PropertyType.IsGeneric) //Possible List/Collection/Dictionary
{
//Here is my issue
Type subType = properties[i].PropertyType.GetGenericTypeDefinition();
bool isAssignable = subType.IsAssignableFrom(typeof(ICollection<>)); //Always false
bool isSubclass = subType.IsSubclassOf(typeof(ICollection<>)); //Always false
//How can I figure if it inherits ICollection/IEnumerable so I can use it's interface to loop through it's elements?
}
else if(properties[i].PropertyType.IsArray) //Array
{
}
else if(properties[i].PropertyType.IsClass && !properties[i].PropertyType.Equals(typeof(String)))
{
//Non-string Subclasses, recursive here
}
else
{
//Value types, write the text + value
}
}
Like mentioned in the comments: use Json as a way to format objects, it will save a lot of time.
If you have reason not to do this, you can check if the type is enumerable: This also covers the Type.IsArray case.
typeof(IEnumerable).IsAssignableFrom(properties[i].PropertyType)
As an added notice of caution: maybe you do not want to enumerate String and byte[] type objects.

C# : LINQ query to list all empty properties of a class

I have a class like this :
public class Test
{
public string STR1{ get; set; }
public INT INT1{ get; set; }
public DOUBLE DBL1{ get; set; }
public DATETIME DT1{ get; set; }
}
Normally, before saving the object, i will have to check all the properties inside this Class, and return a warning message if there is any empty/null property. There is easy way to do this by simply check each property like this :
if (string.IsNullOrEmpty(t.STR1))
return "STR1 is empty"
if (t.INT1 == 0)
return "INT1 = 0";
if (t.DBL1 == 0)
return "DBL1 = 0";
if (t.DT1 == DateTime.MinValue)
return "DT1 is empty"
But what if my class has more properties, actually it contains about 42 properties now, and still growing up. So i was thinking for a "cleaner" way to perform this check, and i found this topic which is quiet similar to my issue : Reflection (?) - Check for null or empty for each property/field in a class?
But this solution does not meet my need as i have to list the values that = null/empty string/0/DateTime.MinValue
Believe me, i wanted to post my "tried code" but i can't figure out a sensible LINQ query for this task (i'm a novice in C#)
Any help is greatly appreciated !
Since you need to test objects of different types, you can combine the solution from the linked question with use of dynamic to dispatch to the proper method.
First, define an overloaded method for each type.
private static IsEmpty(string s) { return string.IsNullOrEmpty(s); }
private static IsEmpty(double f) { return f == 0.0; }
private static IsEmpty(int i) { return i == 0; }
private static IsEmpty(DateTime d) { return d == DateTime.MinValue; }
Now you can use these methods in your check:
List<string> emptyProperties = typeof(MyType).GetProperties()
.Select(prop => new { Prop = prop, Val = prop.GetValue(obj, null) } )
.Where(val => IsEmpty((dynamic)val.Val) // <<== The "magic" is here
.Select(val => val.Prop.Name)
.ToList();
The tricky part of the code casts the value to dynamic, and then tells the runtime to find the most appropriate IsEmpty method for it. The downside to this approach is that the compiler has no way of telling whether the method is going to be found or not, so you may get exceptions at runtime for properties of unexpected type.
You can prevent these failures by adding a catch-all method taking object, like this:
private static IsEmpty(object o) { return o == null; }

C# Generics Efficiency, a better way to do this

Ok, lets say I have classes such as the following:
public class KPIObject<T> //<--This class where T is the following classes
{
public List<T> Data { get; set; }
public string Caption { get; set; }
}
public class KPICycleCountAccuracyData //<--There are 20 of these with different names and values
{
public string Facility { get; set; }
public string CCAdjustedCases { get; set; }
public string TotalCases { get; set; }
public string CCAdjustedPercent { get; set; }
}
Then I have:
public List<ReportData>> ProcessAccountReport(GetAccountReport request)
{
var data = new List<ReportData>();
ProcessKPI(data, request.KPICycleCountAccuracy, "KPICycleCountAccuracy"); //<-- 20 of these
return data;
}
Here is the ProcessKPI method:
private static void ProcessKPI<T>(List<ReportData> data, ICollection<KPIObject<T>> items, string name)
{
if (items == null || items.Count <= 0) return;
foreach (var item in items)
{
if (item.Data == null || item.Data.Count <= 0) continue;
var temp = new List<object>();
temp.AddRange((IEnumerable<object>)item.Data);
data.Add(new ReportData { Data = temp, Name = name, Title = item.Caption });
}
}
All of this works and compiles correctly, I am just wondering if this is the most efficient way of doing this.
Thanks.
EDIT
I changed process KPI to this:
private static void ProcessKPI<T>(ICollection<ReportData> data, ICollection<KPIObject<T>> items, string name)
{
if (items == null || items.Count <= 0) return;
foreach (var item in items.Where(item => item.Data != null && item.Data.Count > 0))
{
data.Add(new ReportData { Data = (IEnumerable<object>)item.Data, Name = name, Title = item.Caption });
}
}
Couple of comments
There is no need to make data a ref parameter in ProcessKPI. A ref parameter is only meaningful for a class type in C# if you actually assign to it. Here you're just modifying the object so ref doesn't by you anything except awkward call syntax
Even though Count is signed it won't ever return a negative value.
I would prefer (IEnumerable<object>)item.Data over the as IEnumerable<object> version. If the latter fails it will result in an ArgumentNullException when really it's a casting issue.
Speed
Assuming you are talking about computational efficiency (i.e. speed), there are two operations that you might be able to improve:
First, you create a copy of the item.Data in the temp variable. When you know that the resulting ReportData will never be modified, you may use the item.Data directly, forgoing the expensive copy operation.
data.Add(new ReportData {
Data = (IEnumerable<object>)item.Data,
Name = name,
Title = item.Caption });
Second, converting to IEnumerable<object> will probably cause unnecessary boxing/unboxing at a later point. See if it makes sense for your application to add a generic type parameter to ReportData, so you may instantiate it as new ReportData<KPIObject>(). That way the compiler may do a better job of optimizing the code.
Memory
By implementing your solution using continuations you may be able to process one ReportData element at a time instead of all at once, thereby reducing the memory footprint. Have a look at the yield statement to see how to impelement such an approach.
Other
For futher code quality improvements, JaredPar's answer offers some exellent advice.

Categories

Resources