Determine if object is any Predicate<T> - c#

I've got an IList<Delegate> that contains some Func<bool>s and some Predicate<T>s, where T varies. I later need to sort out which of these items are Predicate<T>s, but don't want to close the door to adding other Delegate types to the list later, so I do not want to do this by identifying objects by !(current_delegate is Func<bool>).
The highest abstraction below Predicate<T> is MulticastDelegate, which seems unhelpful (would need a non-generic Predicate type under Predicate<T>), and identifying the presence of the generic parameter is also useless given the other generic Delegates that may be present in the list.
The only other thing I've considered is checking the Name of the Type. To me, string comparison is a near-smell, but maybe that is the is the best and/or only way -- you tell me.
What is the best way to definitively determine that an object is any Predicate<T> without knowing the type of T?

Like this:
obj.GetType().GetGenericTypeDefinition() == typeof(Predicate<>)

Predicate<int> pred = ...;
var isPreidcate = pred.GetType().GetGenericTypeDefinition() == typeof(Predicate<>);
On another note, if you have a generic list, you shoulnd't need to check the types in it. You may want to rethink your design if you need to check for specific types within a list.

You can have a list of special classes which wrap your delegates and provide additional sorting information. So you'll indirectly solve the problem.

This should work well enough:
public static bool IsPredicate(object obj) {
var ty = obj.GetType();
var invoke = ty.GetMethod("Invoke");
return invoke != null && invoke.ReturnType == typeof(bool);
}
The trick will be when you actually want to call the function, you will need to use reflection.
Here are some tests:
Func<bool> is pred? True
Func<int, bool> is pred? True
Predicate<int> is pred? True
Func<int> is pred? False

Related

Safe convert function

Can someone explain me this code, especially I'm not sure how generic function as parameter works:
result.Notes= orderInfo.Notes.SafeConvert(x => (Communication.OrderNotes)x);
public static TOut[] SafeConvert<TIn, TOut>(
this TIn[] input,
Func<TIn, TOut> converter)
{
if (input == null)
{
return null;
}
return input
.Where(i => i != null)
.Select(converter)
.ToArray();
}
SafeConvert is a generic extension method. The first parameter (an array of the generic type TIn) is implicitly added when the method is invoked on an array of some type (in this case maybe a note?). The method also requires an function as a parameter. This function must take an instance of the type TIn and return a TOut instance. So, you'd invoke this method on an array of some type, supply a lambda expression or a delegate function, and it will return an array of whatever type your supplied function returns. It does this by using Linq to filter out nulls, run each item in the array through the method, then return the enumeration of those items as an array.
In the implementation you've given, it takes the "Notes" of "orderInfo" and explicitly casts them to "CommunicationOrderNotes."
Here's another way you could invoke the method.
var decimals = new [] {5, 3, 2, 1}.SafeConvert(someInt => (decimal) someInt);
This is what's known as an extension method. It's a static function that allows you to "add" methods to types without modifying the original code. It's somewhat analogous to the Decorator Pattern but there's controversy about whether it's actually an implementation of that particular pattern.
"Under the hood," at least, extension methods are just "syntactic sugar" for calling a static method, but you can call them as if they were an instance method of the extended object (in this case, arrays).
The <TIn, TOut> part means that TIn and TOut are some type you haven't specified yet (but that you intend to specify what they actually are when you go to use the class). To understand the purpose of this, think of a Linked List - really, the implementation of a Linked List of integers isn't any different than the code for a Linked List of strings, so you'd like it to be the case that you can create a single class and specify later that you want a list of integers or a list of strings or whatever. You definitely would not want to have to create an implementation for every single possible type of object - that would require a massive amount of redundant code.
Now, for the LINQ query:
return input
.Where(i => i != null)
.Select(converter)
.ToArray();
LINQ (Language Integrated Query) is a mechanism for querying different types of collections using a single syntax. You can use it to query .NET collections (like they're doing here), XML documents, or databases, for example.
LINQ Queries take an anonymous function of some kind and apply the operator to the collection in some way (see below).
Going through this query;
.Where(i => i != null)
As the name suggests, Where applies a filter. When applied to a collection, it returns a second collection with all of the elements of the first collection that match the filter condition. The
i => i != null
bit is the anonymous function that acts as a filter. Basically, what this is saying is "give me a collection with all of the members of the array that aren't null."
The Select method applies a transform to every element of the collection and returns the result as a second collection. In this case, you apply whatever transformation you passed in as an argument to the method.
It might sound slightly odd to think of code as data, but this is actually very routine in some other languages like F#, Lisp, and Scala. ("Under the hood", C# is implementing this behavior in an object-oriented way, but the effect is the same).
The basic idea of this function, then, is that it converts an array of one type to an array of a second type, filtering out all of the null references.

What's a maintainable way to determine if a value is set to its type's default value?

Say I have some code such as the following:
var someCollection = new int[] {};
var result = someCollection.SingleOrDefault();
I then want to determine if result was the default value. However, I want to do so in a maintainable way so that if the element type of someCollection changes, the rest of the code doesn't require changing.
The way this typically seems to be done (in a general sense) is result == null. In this case, of course, the type is not a reference type, so this won't work.
An improvement that avoids this assumption is result == default(int). However, changing the element type would also require changing the argument to default, so the requirement of only changing the type in one place is still not met.
Acceptance Criteria
Built-in logic is preferred over custom logic.
Elegant and concise code is preferred.
Efficient code is preferred. (For reference types, only a reference comparison should occur.)
You can use the default keyword. Since you don't know what the type will be, you can use generics.
public bool IsDefault<T>(T value)
{
return EqualityComparer<T>.Default.Equals(value, default(T));
}
Stealing from Sam, and improving it:
public static bool IsDefault<T>(this T value)
{
return value == null || value.Equals(default(T));
}
No need for a type check. The JIT will make it work because it knows what T is at JIT time.
Note that if the type overrides Equals then it might say false even
when it is default(T) and it might say true even when it is not.
– commented by Eric Lippert
I think this will work.
public static bool IsDefault<T>(this T value)
{
var isValueType = typeof(T).IsValueType;
if (isValueType)
return value.Equals(default(T));
else
return value == null;
}
However, for value types, I figure this will call their overloaded Equals methods, which may or may not be a problem.

an I prevent a specific type using generic restrictions

I have an overload method - the first implementation always returns a single object, the second implementation always returns an enumeration.
I'd like to make the methods generic and overloaded, and restrict the compiler from attempting to bind to the non-enumeration method when the generic type is enumerable...
class Cache
{
T GetOrAdd<T> (string cachekey, Func<T> fnGetItem)
where T : {is not IEnumerable}
{
}
T[] GetOrAdd<T> (string cachekey, Func<IEnumerable<T>> fnGetItem)
{
}
}
To be used with...
{
// The compile should choose the 1st overload
var customer = Cache.GetOrAdd("FirstCustomer", () => context.Customers.First());
// The compile should choose the 2nd overload
var customers = Cache.GetOrAdd("AllCustomers", () => context.Customers.ToArray());
}
Is this just plain bad code-smell that I'm infringing on here, or is it possible to disambiguate the above methods so that the compiler will always get the calling code right?
Up votes for anyone who can produce any answer other than "rename one of the methods".
Rename one of the methods. You'll notice that List<T> has an Add and and AddRange method; follow that pattern. Doing something to an item and doing something to a sequence of items are logically different tasks, so make the methods have different names.
This is a difficult use case to support because of how the C# compiler performs overload resolution and how it decides which method to bind to.
The first issue is that constraints are not part of the signature of a method and won't be considered for overload resolution.
The second problem you've got to overcome is that the compiler chooses the best match from the available signatures - which, when dealing with generics, generally means that SomeMethod<T>(T) will be considered a better match than SomeMethod<T>( IEnumerable<T> ) ... particularly when you've got parameters like T[] or List<T>.
But more fundamentally, you have to consider whether operating on a single value vs. a collection of values is really the same operation. If they are logically different, then you probably want to use different names just for clarity. Perhaps there are some use cases where you could argue that the semantic differences between single objects and collections of objects are not meaningful ... but in that case, why implement two different methods at all? It's unclear that method overloading is the best way to express the differences. Let's look at an example that lends to the confusion:
Cache.GetOrAdd("abc", () => context.Customers.Frobble() );
First, note that in the example above we are choosing to ignore the return parameter. Second, notice that we call some method Frobble() on the Customers collection. Now can you tell me which overload of GetOrAdd() will be called? Clearly without knowing the type that Frobble() returns it's not possible. Personally I believe that code whose semantics can't be readily inferred from the syntax should be avoided when possible. If we choose better names, this issue is alleviated:
Cache.Add( "abc", () => context.Customers.Frobble() );
Cache.AddRange( "xyz", () => context.Customers.Frobble() );
Ultimately, there are only three options to disambiguate the methods in your example:
Change the name of one of the methods.
Cast to IEnumerable<T> wherever you call the second overload.
Change the signature of one of the methods in a way that the compiler can differentiate.
Option 1 is self-evident, so I'll say no more about it.
Options 2 is also easy to understand:
var customers = Cache.GetOrAdd("All",
() => (IEnumerable<Customer>)context.Customers.ToArray());
Option 3 is more complicated. Let's look at ways we can be achieve it.
On approach is by changing the signature of the Func<> delegate, for instance:
T GetOrAdd<T> (string cachekey, Func<object,T> fnGetItem)
T[] GetOrAdd<T> (string cachekey, Func<IEnumerable<T>> fnGetItem)
// now we can do:
var customer = Cache.GetOrAdd("First", _ => context.Customers.First());
var customers = Cache.GetOrAdd("All", () => context.Customers.ToArray());
Personally, I find this option terribly ugly, unintuitive, and confusing. Introducing an unused parameter is terrible ... but, sadly it will work.
An alternative way of changing the signature (which is somewhat less terrible) is to make the return value an out parameter:
void GetOrAdd<T> (string cachekey, Func<object,T> fnGetItem, out T);
void GetOrAdd<T> (string cachekey, Func<IEnumerable<T>> fnGetItem, out T[])
// now we can write:
Customer customer;
Cache.GetOrAdd("First", _ => context.Customers.First(), out customer);
Customer[] customers;
var customers = Cache.GetOrAdd("All",
() => context.Customers.ToArray(), out customers);
But is this really better? It prevents us from using these methods as parameters of other method calls. It also makes the code less clear and less understandable, IMO.
A final alternative I'll present is to add another generic parameter to the methods which identifies the type of the return value:
T GetOrAdd<T> (string cachekey, Func<T> fnGetItem);
R[] GetOrAdd<T,R> (string cachekey, Func<IEnumerable<T>> fnGetItem);
// now we can do:
var customer = Cache.GetOrAdd("First", _ => context.Customers.First());
var customers = Cache.GetOrAdd<Customer,Customer>("All", () => context.Customers.ToArray());
So can use hints to help the compiler to choose an overload for us ... sure. But look at all of the extra work we have to do as the developer to get there (not to mention the introduced ugliness and opportunity for mistakes). Is it really worth the effort? Particularly when an easy and reliable technique (naming the methods differently) already exists to help us?
Use only one method and have it detect the IEnumerable<T> case dynamically rather than attempting the impossible via generic constraints. It would be "code smell" to have to deal with two different cache methods depending on if the object to store/retrieve is something enumerable or not. Also, just because it implements IEnumerable<T> does not mean it is necessarily a collection.
constraints don't support exclusion, which may seem frustrating at first, but is consistent and makes sense (consider, for example, that interfaces don't dictate what implementations can't do).
That being said, you could play around with the constraints of your IEnumerable overload...maybe change your method to have two generic typings <X, T> with a constraint like "where X : IEnumerable<T>" ?
ETA the following code sample:
void T[] GetOrAdd<X,T> (string cachekey, Func<X> fnGetItem)
where X : IEnumerable<T>
{
}

Generic overloaded method resolution problems

I have two methods with these signatures:
void Method<T>(T data)
{
}
void Method<T>(IEnumerable<T> data)
{
}
Its an overload of the same method to take either a single object or a list of them. If I try to pass a List<'T> to it, it resolves to the first method, when obviosly i want the second. I have to use list.AsEnumerable() to get it to resolve to the second. Is there any way to make it resolve to the second regardless of whether the list is type T[], IList<'T>, List<'T>, Collection<'T>, IEnumerable<'T>, etc.
The best solution: do not go there in the first place. This is a bad design. You'll note that none of the framework classes do this. A list has two methods: Add, and AddRange. The first adds a single item, the second adds a sequence of items.
It's a bad design because you are writing a device for automatically producing bugs. Consider again the example of a mutable list:
List<object> myqueries = new List<object>();
myqueries.Add(from c in customers select c.Name);
myqueries.Add(from o in orders where o.Amount > 10000.00m select o);
You'd expect that to add two queries to the list of queries; if Add were overloaded to take a sequence then this would add the query results to the list, not the queries. You need to be able to distinguish between a query and its results; they are logically completely different.
The best thing to do is to make the methods have two different names.
If you're hell bent on this bad design, then if it hurts when you do that, don't do that. Overload resolution is designed to find the best possible match. Don't try to hammer on overload resolution so that it does something worse. Again, that is confusing and bug prone. Solve the problem using some other mechanism. For example:
static void Frob(IEnumerable ts) // not generic!
{
foreach(object t in ts) Frob<object>(t);
}
static void Frob<T>(T t)
{
if (t is IEnumerable)
Frob((IEnumerable) t);
else
// otherwise, frob a single T.
}
Now no matter what the user gives you - an array of T, an array of lists of T, whatever, you end up only frobbing single Ts.
But again, this is almost certainly a bad idea. Don't do it. Two methods that have different semantics should have different names.
Depends if you are doing this:
var list = new List<Something>();
Method<List<Something>>(list); // Will resolve to the first overload.
Or:
var list = new List<Something>();
Method<Something>(list); // Will resolve to the second overload.
The reason this occurs, is the compiler will select the most specific method it can, so where your generic Method<T>(T data) is used, it is compiled as Method<List<Something>>(List<Something> data), which is more specific than IEnumerable<Something>
The overload resolution will attempt to find the best matching overload.
In the case of the IEnumerable<T> overload, you will indeed need to explicitly convert or use the IEnumerable<T>, as then that will indeed be the best match.
Otherwise, the simple generic overload will be considered a better match.
For a lot more detail, read the "overload resolution" blog entries of Eric Lippert.
It's somewhat unusual to have overloads such that a method can take either a single thing, or a collection of things, isn't it? Why not just have
void MethodSingle<T>(T data)
{
Method(new T[] { data });
}
void Method<T>(IEnumerable<T> data)
{
}
Clearer to both the compiler and the reader, I'd suggest.
Q:
Is there any way to make it resolve to the second regardless of whether the list is type T[], IList<'T>, List<'T>, Collection<'T>, IEnumerable<'T>, etc.
The T[] is not an list but an array, so probably no.
I not sure that this will be helpful but you can try to create a method with restrictions
public void Method<U,T> (U date) where U : IList<T> { /* ... */ }
Why don't expand the method this way:
void Method<T>(T data)
{
var enumerable = data as IEnumerable<T>;
if(enumerable != null)
{
Method(enumerable);
return;
}
...
}

Generic method to cast one arbitrary type to another in c#

I want to do something like this:
public static TResult MyCast<TSource, TResult>(TSource item)
{
return (TResult)item;
}
Without restrictions on TSource or TResult and avoiding unnecessary boxing if possible.
Edit: I want to stress out, that I want a simple casting of types, not elaborate type conversion here. It would be perfectly ok to fail at casting, say string to int.
Is there any sane way to do this using CLR 2.0?
Edit: this is a simplified version, so it's pretty useless, yes.
But consider casting generic collections, such as this:
public static Dictionary<string, TResult> CastValues<TSource, TResult>(this Dictionary<string, TSource> dictionary)
After some discussions with my co-workers, it seems like there's no simple way to implement such a feature (if at all possible), so I'm stuck with code bloat of several very simple methods for different situations (i.e. up- and downcast of reference types and casting of some value types) :(
Too bad I can't use .NET 4.0 with all it's dynamic et al goodness.
How would
x = MyCast<SourceType, ResultType>(y)
be any more useful than
x = (ResultType)y ?
This is straightforward when TSource and TResult are both reference types.
If one or the other are value types, how do you want it to work? Value types can't inherit from each other, so it's not a matter of doing an up- or down-cast. You might expect numeric conversions between, say, int and double, but you'd have to code these yourself: .NET doesn't treat them as typecasts. And conversion between, say, DateTime and string involves more intelligence (what format? which culture? etc.).
If you're just handling reference types then this method can be a one-liner. If you want to handle value types as well then you'll need to write special case code for the various combinations.
Edit: Convert.ChangeType does a reasonable job at encapsulating the various conversions between value types. However you mentioned you're keen not to introduce boxing: Convert.ChangeType isn't generic and it takes an object.
I think that the problem you are trying to solve is the same as the problem that you cannot cast a collection of one type to a collection of another type.
eg
class Obj1
{}
class Obj2:Obj1
{}
List<Obj2> srcList = GetList();
List<Obj1> castedList=(List<Obj2>) srcList;//this line wont compile
I have not done much at actually looking at the CLR code
However on the asuumption that it is like C++ what you would have here is actually different values stored in the collection. In other words srcList would contain a list of pointers to object 2's interface in castedList you would have a pointer to the the interface of the object 1's within object 2.
In order to resolve this you would need to have your casting function iterate through each of the items within the collection. However in order to be able to iterate through the items the list would have to implement some sort of enumeration interface. So the enumeration interface would need to be a constraint on the casting function.
So the answer would therefore be no.
However if you were prepared to implement this with restrictions on the in types you could have:
static class ListCast<TSource,TResult,TItemType>
where TSource:IEnumerable<TItemType>
where TResult:IList<TItemType>,new()
{
static TResult Cast(TSource list)
{
TResult castedList=newTResult();
foreach(TtemType item in list)
{
castedList.Add(TItemType)item);
}
return castedList;
}
}
you can just do this:
public static TResult MyCast<TSource, TResult>(TSource item)
{
return (TResult)((object)item);
}
Would love to hear how this could be bad.

Categories