I have a generic method that I want to pass a variable to, and if that variable is IEnumerable, set all its elements to its default value. This is what I have so far:
public static T set_to_default<T>(T the_obj)
{
var the_enumerable = the_obj as IEnumerable;
if (the_enumerable != null)
{
foreach (var element in the_enumerable)
{
// I don't know what to put here
// I want to set each element to its default value: default(T)
}
return the_obj;
}
else
{
return default(T);
}
}
What do I put inside the foreach loop?
You should just work with overloads, it's much simpler (if I understand your question correctly).
public static T SetToDefault<T>(T the_obj)
{
return default(T);
}
public static IEnumerable<T> SetToDefault<T>(IEnumerable<T> the_enumerable)
{
return the_enumerable.Select(value => default(T));
}
FYI I tested my code with this function:
public static void Test()
{
int myInt = 7;
IEnumerable<int> myEnumberable = new List<int>() { 1, 4, 8, 9 };
myInt = SetToDefault(myInt);
myEnumberable = SetToDefault(myEnumberable);
Console.WriteLine($"MyInt: {myInt}");
Console.WriteLine($"MyEnumberable: {String.Join(", ", myEnumberable)}");
}
To add to this, keep in mind that the name SetToDefault isn't a great choice. When you pass in an int, you will get back an int. You still have to set the value yourself (myInt = SetToDefault(myInt);) which is kind of contradictory to what the name of the function implies.
By the way, note that the first function (T SetToDefault<T>(T the_obj)) has a parameter which is never used. To work around this (to be fair, small) issue, you could use an extension method:
public static class Extensions {
public static T GetDefault<T>(this T value) {
return default(T);
}
}
Note that even here, you will have to set the value to the return of the function. Returning void and simply doing value = default(T); will not work for primitive types like int. That's also why I named it GetDefault instead of SetToDefault this time.
var myWhatever = 3.4;
myWhatever = myWhatever.GetDefault();
Inside the for loop put the following statement:
var default_val = Activator.CreateInstance(element.GetType());
This is how you set to default value
and here is a complete working example of your program
class Program
{
static void Main(string[] args)
{
var my_list = new List<int>() { 1, 2, 3 };
var list2 = set_to_default<List<int>>(my_list);
foreach (var elem in list2)
{
Console.WriteLine(elem);
}
Console.ReadKey();
}
public static T set_to_default<T>(T the_obj)
{
IEnumerable the_enumerable = the_obj as IEnumerable;
if (the_enumerable != null)
{
Type type = the_enumerable.GetType().GetGenericArguments()[0];
Type listType = typeof(List<>).MakeGenericType(new[] { type });
IList list = (IList)Activator.CreateInstance(listType);
var looper = the_enumerable.GetEnumerator();
while (looper.MoveNext())
{
var current_obj = looper.Current;
current_obj = Activator.CreateInstance(current_obj.GetType());
list.Add(current_obj);
}
return (T)list;
}
else
{
return default(T);
}
}
}
I suggest to use lists instead of enumerables because the last ones are immutable. That is once you create them you cannot edit them.
Final thing....if you want to support other types of IEnumerable the are not IList you may use the C# 'is' keyword to figure it out. In this case you need to know the underlying type of your enumerable at run-time. You may do that using the C# 'is' keyword
if (the_enumerable is IList)
{
editableType = typeof(List<>).MakeGenericType(new[] { type });
}
else if(the_enumerable is ICollection)
{
......
}
Related
I have a generic list. I have to filter the list based on the value of the property of list item. Item type is not known until runtime.
I have to find the item type by reflection and then need to filter.
Please help me by any idea or example
Thanks.
I Hope this help
pass any list, and specify a property name, and a filter method
private IList FilterList(IList list, string propName, Predicate<object> filterMethod) {
var result = new List<object>();
foreach (var item in list) {
var value = item.GetType().GetProperty(propName).GetValue(item);
if (filterMethod(value)) {
result.Add(item);
}
}
return result;
}
Example :
var result = FilterList(list, "Age", age => (int)age >= 18);
you can develop it and make it fully dynamic
If the list is generic you should know at least a base type at compile time.
If the base type contains the property - just use it.
If only some of the subtypes(ideally one) contain the property you're interested in you can do a cast on the list and then use your property.
list.Cast<Derived>().Select(i => i.Property == "val");
If that is not ok(say the type of the list has many derived types that contain the property and others that do not), you can use dynamic with a try/catch block.
list.Select(i => {
try
{
dynamic item = i;
return item.Prop == "value";
}
catch(RuntimeBinderException) //this type doesn't contain the property
{
return false;
}
});
Try this. It can determine whether a List is a list of some specified type. Based on that you should be able to filter for any specific type.
public class TypeA
{ }
public class TypeB
{ }
public class GenericFilter
{
public bool IsOfType<T>(IEnumerable<dynamic> objectToInspect)
{
var genericType = objectToInspect.GetType().GenericTypeArguments[0];
return genericType == typeof(T);
}
}
[TestClass]
public class UnitTest1
{
[TestMethod]
public void IdentifiesExpectedType()
{
var classToInspect = new List<TypeA>();
var filter = new GenericFilter();
Assert.IsTrue(filter.IsOfType<TypeA>(classToInspect));
}
[TestMethod]
public void RejectsNonMatchingType()
{
var classToInspect = new List<TypeA>();
var filter = new GenericFilter();
Assert.IsFalse(filter.IsOfType<TypeB>(classToInspect));
}
}
This works just as well:
public bool IsOfType<T>(IEnumerable<dynamic> listToFilter)
{
return (listToFilter as IEnumerable<T>) != null;
}
This will take a list of lists and group them into a Dictionary<Type, List<List<dynamic>> where all of the lists for each key are of that type. That way you can select lists of type T just by retrieving them from the dictionary.
public Dictionary<Type, List<List<dynamic>>> GroupListsByType(List<List<dynamic>> lists)
{
var types = lists.Select(list => list.GetType().GenericTypeArguments[0]).Distinct().ToList();
var grouped = new Dictionary<Type, List<List<dynamic>>>();
types.ForEach(type =>
{
grouped.Add(type, new List<List<dynamic>>());
grouped[type].AddRange(lists.Where(list=>list.GetType().GenericTypeArguments[0] == type));
});
return grouped;
}
(I'm not questioning the "why." I don't know if I would recommend this, but it's interesting to write.)
Currently I have a list containing structs, and I use a delegate to find a struct in the list as such:
stTest item = myList.Find(delegate(stTest test)
{
return ( string.Compare(test.StringA, somestring, true) == 0 );
});
This has been working perfectly for getting an item, but it seems that it returns a copy of the item it found and not the actual item, so if I modify fields in the item (which I do), the updates don't take effect on the item in the list.
Is there any way to get the delegate to return a reference to the item in the list?
If you are trying to mutate the object in-place, you can "fake it" with a slightly nicer syntax by employing an extension method like this:
public delegate void Mutator<T>(ref T arg) where T : struct;
public static void FindAndMutate<T>(
this IList<T> self,
Predicate<T> predicate,
Mutator<T> mutator) where T : struct
{
if (self == null) { throw new ArgumentNullException("self"); }
if (predicate == null) { throw new ArgumentNullException("predicate"); }
if (mutator == null) { throw new ArgumentNullException("mutator"); }
for (int i = 0; i < self.Count; ++i) {
var value = self[i];
if (predicate(value)) {
mutator(ref value);
self[i] = value;
}
}
}
The usage would look something like this:
struct AStruct
{
public string String;
public int Int;
}
var list = new[] {
new AStruct() { String = "hello", Int = 0},
new AStruct() { String = "world", Int = 1}
};
list.FindAndMutate(i => i.Int == 0, (ref AStruct i) => i.String = "goodbye");
This is obviously not a perfect solution, and does involve copying of the struct inside of the extension method.
Really, if you need reference semantics you should be using a reference type instead of a value type.
item=myList.FirstOrDefault(entry=>
string.Compare(entry.StringA, someString, true)==0);
Note that struct is not a reference type, you cannot do that, unless you want to box it into a reference type, but that will bring additional overhead.
If you really want to use reference, consider to repalce your struct with class.
It will work if you change the list members from struct to class, because structs are always copied.
At the run-time I get boxed instance of some type. How to unbox it to underlying type?
Object obj;
String variable = "Some text";
obj = variable // boxing;
// explicit unboxing, because we know the type of variable at compile time.
var x = (String)obj
// Now let's pretend that we don't know the type of underlying object at compile time.
Type desiredType = obj.GetType(); // But we can figure out.
//And now the question.
//How to express something like this:
var y = (desiredType)obj; //Need to get unboxed instance of initial variable here;
If you don't know the type at compile time, then you can't unbox because you have nowhere to put it - all you can do is store it in an object, which is: boxed.
The same also applies to reference-types like string: you can't cast it to the right type if you don't know the type at compile time: you have nowhere to put it.
You can special-case a few types, for example:
if(obj is int) {
int i = (int)obj;
...
} ...
Another trick that is sometimes (not often) helpful is to switch into generics; then instead of talking in terms of object you are talking in terms of T. This has... limited use though. The easiest way to do that is via dynamic, for example:
dynamic obj = ...
Foo(obj);
...
Foo<T>(T val) { ... code with T ... }
you can also add special cases to that appreach:
Foo(string val) { ... code with string ...}
Foo(int val) { ... code with int ...}
However, frankly I suggest it may be better to look hard at what you are trying to do.
Now lets suppose, that real boxing occur:
int v = 5;
object o = v; //boxed
Type type = o.GetType(); //will return typeof(int)
int convertedBack = (int)Convert.ChangeType(o, type);
Console.WriteLine (convertedBack); //prints 5
Remark, if you substitute:
object convertedBack = Convert.ChangeType(o, type);
Console.WriteLine (convertedBack); //it still prints 5
Console.WriteLine (o); //it even print 5 here
The reason is that underlying object is still int. I've just used this example to show you, that boxing is irrelevant here. You need to rely on some abstraction in your operations and if you want to cast to int dynamically, what reference type do you wan to use.
In such cases I'm going to use the strategy pattern by using a Dictionary<Type, Action<object>>:
internal class Program
{
private static void Main(string[] args)
{
var something = new Something();
something.ComputeValue(13);
something.ComputeValue(DateTime.Now);
something.ComputeValue(DayOfWeek.Monday);
Console.ReadKey();
}
}
internal class Something
{
private static Dictionary<Type, Action<object>> _Strategies;
static Something()
{
// Prepare all available strategies.
_Strategies = new Dictionary<Type, Action<object>>();
_Strategies.Add(typeof(int), ComputeInteger);
_Strategies.Add(typeof(DateTime), ComputeDateTime);
}
public void ComputeValue(object value)
{
Action<object> action;
// Check if we have a matching strategy.
if (!_Strategies.TryGetValue(value.GetType(), out action))
{
// If not, log error, throw exception, whatever.
action = LogUnknownType;
}
// Perform the matching strategy on the given value.
action(value);
}
private static void ComputeDateTime(object source)
{
// We get an object, but we are sure that it will always be an DateTime.
var value = (DateTime)source;
Console.WriteLine("We've got an date time: " + value);
}
private static void ComputeInteger(object source)
{
// We get an object, but we are sure that it will always be an int.
var value = (int)source;
Console.WriteLine("We've got an integer: " + value);
}
private static void LogUnknownType(object source)
{
// What should we do with the drunken sailor?
var unknownType = source.GetType();
Console.WriteLine("Don't know how to handle " + unknownType.FullName);
}
}
Here's an example of exactly why you would do this:
class MyClass
{
public int Id {get;set;}
public string Name {get;set;}
public decimal Val {get;set;}
}
int i = 0;
var myClassImp = new MyClass();
foreach (var val in new [object]{"10", "My name", "100.21"} // Could be read from some data source, such as an excel spreadsheet
{
var prop = typeof(MyClass).GetProperties().ElementAt(i++);
// !!!!!! THROWS EXCEPTION !!!!!!!
prop.SetValue(myClassImp, System.Convert.ChangeType(val, prop.PropertyType), null);
}
The reason for this is because the value is a boxed object... at runtime you do not know the type, so you would have to unbox to the prop.PropertyType
A pragmatic solution; try and use a TypeConverter directly, and if that fails, convert to string and back again:-
private static T GetValueOfType<T>(this ManagementBaseObject MBO, String FieldName) {
T lResult;
try {
Object lObj = MBO[FieldName];
var lSrcType = lObj.GetType();
var lDestType = typeof(T);
if (lDestType.IsValueType && lDestType.IsAssignableFrom(lSrcType)) {
lResult = (T)lObj;
return lResult;
}
var lDestTC = TypeDescriptor.GetConverter(typeof(T));
if (lDestTC.CanConvertFrom(lSrcType)) {
lResult = (T)lDestTC.ConvertFrom(lObj);
} else {
var lSrcTC = TypeDescriptor.GetConverter(lSrcType);
String lTmp = lSrcTC.ConvertToInvariantString(lObj);
lResult = (T)lDestTC.ConvertFromInvariantString(lTmp);
}
} catch {
lResult = default(T);
}
return lResult;
}
Use expressions:
var y = DynamicCast(obj, desiredType);
static object DynamicCast(object source, Type type)
{
var parameter = Expression.Parameter(typeof(object), "input");
var cast = Expression.TypeAs(Expression.Convert(parameter, type), typeof(object));
var lambda = Expression.Lambda<Func<object, object>>(cast, parameter);
var func = lambda.Compile();
return func(source);
}
public static string GetType(object data)
{
Type type = data.GetType();
return Convert.ChangeType(data, type).GetType().Name;
}
Hi,this method receives object data and returns string type name of object.
Hope this is what you need.
you can try using the dynamic runtime
[Test]
public void Test_UnboxingAtRuntime()
{
object boxed = "Hello";
//this line is commented out as it does not compile
// OverloadedMethod(boxed);
var result = CallCorrectMethod(boxed);
Assert.That(result, Is.EqualTo("string"));
boxed = 1;
result = CallCorrectMethod(boxed);
Assert.That(result, Is.EqualTo("int"));
}
public string CallCorrectMethod(dynamic t)
{
return OverloadedMethod(t);
}
public string OverloadedMethod(string s)
{
return "string";
}
public string OverloadedMethod(int s)
{
return "int";
}
I'm trying to get the value of a specified index of a property using reflection.
This answer works for standard properties that are of type List<> for example, but in my case, the collection I am trying to work with is of a different format:
public class NumberCollection : List<int>
{
public NumberCollection()
{
nums = new List<int>();
nums.Add(10);
}
public new int this[int i]
{
get { return (int) nums[i]; }
}
private List<int> nums;
}
public class TestClass
{
public NumberCollection Values { get; private set; }
public TestClass()
{
Values = new NumberCollection();
Values.Add(23);
}
}
class Program
{
static void Main(string[] args)
{
TestClass tc = new TestClass();
PropertyInfo pi1 = tc.GetType().GetProperty("Values");
Object collection = pi1.GetValue(tc, null);
// note that there's no checking here that the object really
// is a collection and thus really has the attribute
String indexerName = ((DefaultMemberAttribute)collection.GetType()
.GetCustomAttributes(typeof(DefaultMemberAttribute),
true)[0]).MemberName;
// Code will ERROR on the next line...
PropertyInfo pi2 = collection.GetType().GetProperty(indexerName);
Object value = pi2.GetValue(collection, new Object[] { 0 });
Console.Out.WriteLine("tc.Values[0]: " + value);
Console.In.ReadLine();
}
}
This code gives an AmbiguousMatchException ("Ambiguous match found."). I know my collection class is somewhat contrived, but can anyone help with this?
One option is to use
var prop = Type.GetProperties()
.Where(prop => prop.DeclaringType == collection.GetType())
.First();
Change Collection.GetType() to another type if you want. But basically: loop over the properties instead of using Type.GetProperty.
If you are looking for all of the default members, you can ask for Type.GetDefaultMembers(), then examine the members to find the one that you are looking for.
Alternatively, if you know the data type of the indexer, you can call GetPropertyInfo with the type array specifier.
I have an enumeration for my Things like so:
public enum Things
{
OneThing,
AnotherThing
}
I would like to write an extension method for this enumeration (similar to Prise's answer here) but while that method works on an instance of the enumeration, ala
Things thing; var list = thing.ToSelectList();
I would like it to work on the actual enumeration instead:
var list = Things.ToSelectList();
I could just do
var list = default(Things).ToSelectList();
But I don't like the look of that :)
I have gotten closer with the following extension method:
public static SelectList ToSelectList(this Type type)
{
if (type.IsEnum)
{
var values = from Enum e in Enum.GetValues(type)
select new { ID = e, Name = e.ToString() };
return new SelectList(values, "Id", "Name");
}
else
{
return null;
}
}
Used like so:
var list = typeof(Things).ToSelectList();
Can we do any better than that?
Extension methods only work on instances, so it can't be done, but with some well-chosen class/method names and generics, you can produce a result that looks just as good:
public class SelectList
{
// Normal SelectList properties/methods go here
public static SelectList Of<T>()
{
Type t = typeof(T);
if (t.IsEnum)
{
var values = from Enum e in Enum.GetValues(type)
select new { ID = e, Name = e.ToString() };
return new SelectList(values, "Id", "Name");
}
return null;
}
}
Then you can get your select list like this:
var list = SelectList.Of<Things>();
IMO this reads a lot better than Things.ToSelectList().
No.
The best you can do is put it on a static class, like this:
public static class ThingsUtils {
public static SelectList ToSelectList() { ... }
}
Aaronaught's answer is really great, based on that I made the following implementation:
public class SelectList
{
public static IEnumerable<Enum> Of<T>() where T : struct, IConvertible
{
Type t = typeof(T);
if (t.IsEnum)
{
return Enum.GetValues(t).Cast<Enum>();
}
throw new ArgumentException("<T> must be an enumerated type.");
}
}
In my opinion it's a little bit safer, as you can - almost - call it only with Enums, and of course instead of the throw you can simply return null if you want an exception-free version.
I use 'Type' instead of 'Enum' to add extension. Then I can get any type of list back from the method. Here it returns string values:
public static string[] AllDescription(this Type enumType)
{
if (!enumType.IsEnum) return null;
var list = new List<string>();
var values = Enum.GetValues(enumType);
foreach (var item in values)
{
// add any combination of information to list here:
list.Add(string.Format("{0}", item));
//this one gets the values from the [Description] Attribute that I usually use to fill drop downs
//list.Add(((Enum) item).GetDescription());
}
return list.ToArray();
}
Later I could use this syntax to get what I want:
var listOfThings = typeof (Things).AllDescription();
#Aaronaught has a very good answer. To extend his answer, you can also even make it more generic. I have this in a global library...
public static IQueryable GetAllEnumValues<T>()
{
IQueryable retVal = null;
Type targetType = typeof(T);
if(targetType.IsEnum)
{
retVal = Enum.GetValues(targetType).AsQueryable();
}
return retVal;
}
Now you have de-coupled this functionality from the SelectList class. So you can call this in your SelectList methods, or anywhere else for that matter.
public class SelectList
{
public static SelectList Of<T>
{
IQueryable enumValues = GetAllEnumValues<T>();
var values =
from Enum e in enumValues
select new { ID = e, Name = e.ToString() };
return new SelectList(values, "Id", "Name");
}
}
In my opinion, this is the cleanest way. Why?
It works for any System.Enum
The extension method itself is cleaner.
To call it you just add new and that's a small trade off (because it has to have an instance in order to work.
You aren't passing null around and it literally won't compile if you try to use it with another type.
Usage:
(new Things()).ToSelectList()
Extension Method:
[Extension()]
public SelectList ToSelectList(System.Enum source)
{
var values = from Enum e in Enum.GetValues(source.GetType)
select new { ID = e, Name = e.ToString() };
return new SelectList(values, "Id", "Name");
}
The closest you can come, I think, is to dummy things up a bit to work like an enum without being one. Here's what I've come up with--it seems like a lot of work just to plop a static method on an enumeration, although I do understand the programming appeal of it:
public class PseudoEnum
{
public const int FirstValue = 1;
private static PseudoEnum FirstValueObject = new PseudoEnum(1);
public const int SecondValue = 2;
private static PseudoEnum SecondValueObject = new PseudoEnum(2);
private int intValue;
// This prevents instantation; note that we cannot mark the class static
private PseudoEnum() {}
private PseudoEnum(int _intValue)
{
intValue = _intValue;
}
public static implicit operator int(PseudoEnum i)
{
return i.intValue;
}
public static implicit operator PseudoEnum(int i)
{
switch (i)
{
case FirstValue :
return FirstValueObject;
case SecondValue :
return SecondValueObject;
default:
throw new InvalidCastException();
}
}
public static void DoSomething(PseudoEnum pe)
{
switch (pe)
{
case PseudoEnum.FirstValue:
break;
case PseudoEnum.SecondValue:
break;
}
}
}