I already know that you can pass an interface as a parameter to a method. This allows you to specify only the relevant members of an object required by a method. What I would like to do is to be able to pass an interface type as a parameter.
Say I declared several interfaces, which were implemented un-evenly across a range of objects that all form a single list/collection. Could I write a helper method which would take both an object from the list and an interface type as a parameter, and check if the object implements the interface? The following code is obviously rubbish, but it illustrates the sort of thing I want to do:
private bool CheckType(object o, interface intrfce)
{
try
{
object x = (object)(intrfce)o;
return true;
}
catch (InvalidCastException e)
{
return false
}
}
At the moment I'm simply planning on setting up an enum for the interfaces, and requiring all classes to expose an array/list of interfaces they implement. I can then just check the enum list to see what interfaces they have that are relevant (I'm only interested in the interfaces I have created - I'm not after returning IEnumerable or ICloneable etc.) Or I could write helper methods for each interface. I was just wondering if there was a more elegant way of doing it?
You can do it using generics:
private bool CheckType<T>(object o) {
return o is T;
}
You call it like this:
foreach (object o in myList) {
if (CheckType<MyInterface>(o)) {
... // Do something
}
}
Considering how easy it is to do, you might as well do it in the conditional itself.
Finally, if you wish to process only objects implementing a particular interface in a mixed list, you could do it with LINQ's OfType method, like this:
foreach (MyInterface o in myList.OfType<MyInterface>()) {
...
}
You can do something like:
private bool CheckType(object o, params Type[] types)
{
//you can optionally check, that types are interfaces
//and throw exceptions if non-interface type was passed
if(types.Any(type => !type.IsInterface))
throw new Exception("Expected types to have only interface definitions");
return types.All(type => type.IsAssignableFrom(o.GetType()));
}
CheckType(new List<int>(), typeof(IEnumerable), typeof(IList)); //returns true
CheckType(0, typeof(IEnumerable)); //return false
To check a sequence of objects, you can use something along:
private bool CheckAllType(IEnumerable<object> items, params Type[] types)
{
return items.All(item => CheckType(item, types));
}
Related
I have this abstract class, and implementations, which has an Input type and Output type:
public abstract class Action<TInput, TOutput>
{
public Action() {}
public virtual TOutput Execute(TInput input)
{
throw new NotImplementedException();
}
}
public class Foo<int, string> : Action<int, string>
{
public override string Execute(int i)
{
...
}
}
public class Bar<string, int> : Action<string, int>
{
public override int Execute(string s)
{
...
}
}
How can I hold these imp. in a Collection and loop through them?
like:
actions.Add(new Foo());
actions.Add(new Bar());
object obj;
foreach(var item in actions)
obj = item.Execute(obj);
You can't. At least not with Execute remaining type safe.
What you can do is create another base class or an interface that declares an Execute method that receives and returns an object:
public interface IAction {
object Execute(object input);
}
public abstract class Action<TInput, TOutput> : IAction {
public object Execute(object input) {
return Execute((TInput) input);
}
public virtual TOutput Execute(TInput input)
{
throw new NotImplementedException();
}
}
This will then work (it will compile):
List<IAction> actions = new List<IAction>();
actions.Add(new Foo());
actions.Add(new Bar());
object obj;
foreach(var item in actions)
obj = item.Execute(obj);
However! Keep in mind that this will compile but produce a runtime error:
IAction action = new Foo(); // Expects an integer
action.Execute("I'm not an integer");
The string will be cast to object and then to int, which won't work.
You can't quite do what you're trying to do.
actions.Add(new Foo()); // expects and returns string
actions.Add(new Bar()); // expects and returns int
object obj;
foreach(var item in actions)
obj = item.Execute(obj);
If Foo expects string and Bar expects int (and technically any implementation could expect any other type) then what value can you pass to each item in the collection that will work with all of them? Also, what would you do with the return values, since each of them could be of a different type?
You can solve the problem of getting it compile by declaring the inputs and outputs as object, although that would defeat the purpose of making it generic. You would just replace your base class with this...
public abstract class Action
{
public abstract object Execute(object input);
}
...but that wouldn't be a very useful class.
But the real problem is that methods that receive and return object aren't usually very useful either. The type system allows us to know the types of arguments, return values, variables, etc. That's part of what indicates the intent of our code. For example, we write a method like this:
bool IsAnagram(string input)
because we want to know if (bool) an input (string) is an anagram. Knowing that it does that is our reason for calling it. If we don't want to know if a string is an anagram, we don't call this method because we don't need it.
But what if we have a method like this:
object GetResult(object input)
It has no reason to exist. Why would we call it? If we have a value of some type and we want to do something with it and get some result, we would write a method that does that.
Similarly, if we get back object from the method, what do we do with it? We don't know what it is. It's a bit like going to the store to buy something, except we have nothing in mind that we want to buy, and they hand us a package and we don't know what's inside. We couldn't have any plans for what we intended to do when we got it, since we didn't know what we would get. So we just wouldn't do it.
It only makes sense to use object in specific scenarios where we don't care what the type is. Those scenarios are less common because in order for our application to do anything it almost always needs to be doing something with specified types - creating them, getting them from somewhere, passing them to other methods, and getting more expected types in return.
If you just want a collection of things to do, and they all take different arguments and return different types, then you have to declare the collection according to its least common denominator, which is just Action with no arguments and no return values.
You could do this:
var actions = new List<Action>();
actions.Add(() =>
{
var foo = new Foo();
foo.Execute(5);
});
actions.Add(() =>
{
var bar = new Bar();
bar.Execute("Hello!");
});
foreach (var action in actions)
{
action.Invoke();
}
...and there may be cases where a collection of Action is useful. But in most cases there's no reason to take a bunch of unrelated actions that do different things and put them in a collection with each other.
public static object GetObject(int x)
{
return new object { };
}
public static object GetObject(string x)
{
return new object { };
}
public static void ProcessObject<T>(T x) where T : int, string <= got error here:
{
object o = GetObject(x);
}
Got error "A type used as a constraint must be an interface, a non-sealed class or a type parameter."
How can I rewrite the code to get it work without write ProcessObject(int x) and ProcessObject(string x) twice?
So what you have now (according to accepted answer and your comments) is:
public static void ProcessObject<T>(T x)
{
object o;
if (typeof(T) == typeof(int))
o = GetObject((int)(object)x);
else if (typeof(T) == typeof(string))
o = GetObject((string)(object)x);
else
throw new Exception();
// do stuff with o
}
I'd recommend making public int and string overloads, but to prevent code duplication, internally call another method:
public static void ProcessObject(int x)
{
ProcessObject(GetObject(x));
}
public static void ProcessObject(string x)
{
ProcessObject(GetObject(x));
}
private static void ProcessObject(object o)
{
// do stuff with o
}
This makes your public methods' input values clear: int and string are the only acceptable types, while still not duplicating your actual logic (// do stuff with o).
You might dislike that the two public ProcessObject methods are duplicates of each other, (on the surface anyway; under the hood, they're calling two different GetObject overloads) but I think it's the best option.
You cannot do what you are trying to do: first, it is not possible to list several classes in a generic constraint; second, the type that you can put in a constraint must be such that you could inherit it (or implement it if it is an interface). Both int and string fail this check. In cases like this, you would be better off with two separate overloads.
Just remove the where part
public static void ProcessObject<T>(T x)
{
object o = GetObject(x);
}
And also don't use object in your other methods, instead use T
it's impossible in C# take a look on Constraints on Type Parameters. Try to use dynamic
Generally speaking, if your object reacts differently based on the generic type argument, you probably shouldn't be using generics in this case. Generics are great for situations where you want to do always the same thing, no matter what the actual type used.
Therefore, generic constraints will only allow you to list one base class for a type argument. Any actual types passed to the respective type arguments are meant to be a part of the given inheritance hierarchy starting with the base class you specified, so users of your class can specify any type that matches the base class or any of its subclasses.
At the same time, you, the author of the generic class, can safely assume that the specified type has (at least) the interface of the base class indicated by the constraint. Hence, you may access any members of the base class.
If you want to allow either string or int, imagine what members that could be. Both are derived directly from System.Object, hence the restriction would make no sense as it is no restriction; every type is derived from System.Object.
Summarizing, if you really want to treat string and int differently, this is definitely a case for offering two overloads rather than one generic class.
This issue has been bugging me for a while. Abstractly speaking, regardless of language, there are often situations when you want to have a method like this:
Collection method(Collection c) {
// select some elements from c based on some filter
// and return a new collection
}
Now, Collection is in this case some abstract class (Like say IList in C# or List in Java) with several implementations. I've been wondering what exactly is the right procedure to produce the abstract collection?
Is it ok to create a concrete collection inside the method and return it? Like:
Collection method(Collection c) {
Collection cc = new ConcreteCollection();
// select some elements from c based on some filter
return cc;
}
This of course puts a constraint on the resulting collection and will produce problems in case, for some reason, we want to cast the result of the method to a different concrete collection than the one used inside the method.
Or, use reflection to determine the actual concrete type of c and create an instance of that class:
Collection method(Collection c) {
Collection cc = c.getClass().newInstance();
// select some elements from c based on some filter
return cc;
}
For some reason this does not seem very "elegant" to me. I would greatly appreciate some insight in this matter.
(Speaking for java). The reason you're returning Collection (an interface) rather than a concrete type (such as ArrayList) is that you're telling the user that they shouldn't care about what the actual concrete type being used is. This leaves you free to choose the appropriate type for your library/api.
If you're enforcing a particular concrete class, then you should be returning that concrete class, rather than the interface.
So, they shouldn't be casting your return type to anything else other than Collection. See
When should I return the Interface and when the concrete class?.
In Java, there are actually some good examples of how to do this in the java.util.Collections class. Instead of taking a Collection and returning a Collection, the key methods take two collections, the "src" and the "dest". For example, Look at the signature of the copy method:
public static <T> void copy(List<? super T> dest, List<? extends T> src)
This puts the responsibility of instantiating the destination list on the caller.
I think you could do the same thing when you want to create a method that acts on a src Collection and puts the results into a destination Collection (rather than Lists).
I agree with Matthew Farwell's answer that you probably just want to return the interface and utilize that, but for the times when you really do need to work with a specific implementing class you can do it the same way the Collections class does it.
One approach you could take is to create a Collection implementation that delegates calls through to the original Collection. This defers the potentially expensive operation of filtering a large Collection until you need to explicitly read elements. It also saves memory.
Example
public interface Filter<T> {
boolean include(T t);
}
public class FilterCollection<T> implements Collection<T> {
private final Collection<T> orig;
private final Filter<T> filter;
public FilterCollection(Collection<T> orig, Filter<T> filter) {
this.orig = orig;
this.filter = filter;
}
public int size() {
int sz = 0;
for (T t : orig) {
if (filter.include(t)) {
++sz;
}
}
return sz;
}
public boolean contains(Object o) {
return o instanceof T && filter.include((T) o) && orig.contains(o);
}
public boolean add(T t) {
if (!filter.include(t)) {
throw new IllegalArgumentException("Element lies outside filter bounds.");
}
orig.add(t);
}
}
The caller should assume a given type of Collection is returned.
Instead it should either copy to the desired type or pass the desired type.
e.g.
Set<T> set2 = new HashSet<T>(filter(set));
List<T> list2 = new ArrayList<T>(filter(list));
or
filter(set2, set); // the target collection is passed.
filter(list2, list);
To the question about ConcreteCollection, it is definitely allowable.
To the concern about having a different concrete collection expected, there are a few ways to go around the problem:
Change the return type of the method. Example:
ConcreteCollection method(Collection c){
ConcreteCollection cc=new ConcreteCollection
for(Object x: c){
//do something
}
return cc
}
Make use of polymorphism. Example:
Collection x=method(c)
x.add(new Object) //add is a method defined within the abstract Collection
Use some utilities to cast the type. Example:
LinkedList h=Collections.toLinkedList(method(c))
Hoped my answer helped. ^^
As far as I can understand, you want to know how to make a method that accepts generic list and returns another modified generic list.
So, my advice will be to use an abstract type that implements method to modify its state.
IList<object> list = new List<object>();
list.Add(new object());
list.Remove(obj);
Or as showed above, instantiate a list that implements IList (or the Java equivalent) work with this instance and return the result as a IList
Edit
If you want to filter some item from a list to a new one, generics can help (I don't know if this feature exists in Java).
public IList<T> Filter<T>(IList<T> list)
{
var result = new List<T>();
result.Add(list[0]); // Or whatever filtering method
return result;
}
If you want your method to accept as many different collection types as possible, and you want to be sure that the result is the same implementation type as what you put in, you might want to use a void method which directly modifies the supplied collection. For instance:
import com.google.common.base.Predicate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
public class Testy {
private static <T> void filter(Iterable<T> collection, Predicate<T> filter) {
Iterator<T> iterator = collection.iterator();
while (iterator.hasNext()) {
if (!filter.apply(iterator.next())) { // Condition goes here
iterator.remove();
}
}
}
public static void main(String... args) {
List<String> list = new ArrayList<String>();
list.addAll(Arrays.asList("A", "B", "C", "D"));
filter(list, new Predicate<String>() { // Anonymous filter (predicate)
#Override public boolean apply(String input) {
return input.equals("B");
}
});
System.out.println(list); // Prints ["B"]
}
}
The helper method filter takes an Iterable, the simplest type required for iterating over something. Apply the filter to each element, and if the predicate (filter) returns false, remove that element from the underlying collection with Iterator.remove().
The Predicate<T> interface here comes from Google. You can easily write your own if you don't wish to import it. The only required method is apply(T) which returns a boolean. Either that, or just write your condition directly inside the loop and get rid of the second parameter.
This method is the most efficient if your original collection is mutable and you don't wish to keep any intermediate results.
Another option is to use Google Collections Collections2.filter(Collection<E>, Predicate<E>) which returns a Collection<E> just like in your question. Similarly, the Iterables class will do the same thing, but create lazy iterables where the filters are only applied when actually doing the iterating.
I'm trying to store types in a collection, so that i can later instantiate objects of the types in the collection. But I'm not sure how to do this the best way.
What i have so far:
List<Type> list = new List<Type>();
list.Add(typeof(MyClass));
var obj = (MyClass)Activator.CreateInstance(list[0]);
I would like to have some constrains on the Type, or better yet, just a generic type in the collection instead of an instantiated Type object. Is this possible?
That's not how generic collection constraints work.
Generic constraints restrict which types are legal for instantiating a generic type. There are several different kinds of constraints, but the common ones limit a generic parameter to either inherit or be an instance of a given type, or be a type that implements a particular interface (or set of interfaces).
Type, on the other hand, is a class that describes information about a type in your application or one of it's libraries. Specific kinds of types don't inherit or extend Type - rather there is a different instance of Type for each type available. You cannot use generic constraints to control which instances of Type may be added to your collection.
Without more detail about how you want to "constrain" the information in the collection, it's hard to say what route you should take. For example, if all you want to do is ensure that only unique types (no dups) are stored, that can be achieved with a HashSet (rather than a list). But if you want something more specialized - like limiting the Type instances that can be added to some subset of types, then you will likely need to implement your own collection, and implement gaurd logic in the Add/Insert methods.
In this particular scenario, where it seems we have a "factory" pattern, we would constrain the method invoking the activator, such as
private readonly List<Type> _supportedTypes = new List<Type> ();
public void RegisterSupportedType<T> () where T : SomeConstraintType
{
_supportedTypes.Add (typeof (T));
}
// if we do not know the type, but somehow know an index to type
public object Create (int supportedTypeIndex)
{
object untyped = Activator.
CreateInstance (_supportedTypes[supportedTypeIndex]);
return untyped;
}
// if we know instance type\subtype (eg interface) and know an index
public T Create<T> (int supportedTypeIndex)
{
T typed = default (T);
object untyped = Create (supportedTypeIndex);
if (!(untyped is T))
{
// throw meaningful exception :)
}
typed = (T)(untyped);
return typed;
}
An alternative, is to create a constrained Type
public class ConstrainedType<T>
{
public Type Type { get; private set; }
public ConstrainedType (Type type)
{
// may have this backward, would have to fact check before
// rolling out to prod ;)
if (!typeof (T).IsAssignableFrom (type))
{
// throw meaningful exception!
}
Type = type;
}
}
List<ConstrainedType<SomeTypeConstraint>> list =
new List<ConstrainedType<SomeTypeConstraint>> ();
// will throw meaningful exception if MyClass is not
// SomeTypeConstraint or a sub class
list.Add (new ConstrainedType (typeof (MyClass)));
SomeTypeConstraint baseType =
(SomeTypeConstraint)(Activator.CreateInstance(list[0].Type));
Jon,
If you are using CodeContracts, you could require a number of known types. The code analysis would flag any calls to your collection with invalid types.
public class TypeCollection : List<Type>
{
public TypeCollection()
{
}
public new void Add(Type type)
{
Contract.Requires(type == typeof(string) || type == typeof(Stream));
base.Add(type);
}
}
public class TestCollection
{
public void Test()
{
TypeCollection collection = new TypeCollection();
// This gets compile time warning:
collection.Add(typeof(int));
}
}
But, if you know the types in advance, it might make more sense to specify them all in an enum and create a collection of valid enums for the type creation you want to support.
first way(seems stupid but it is safe):
(create a wrapper over the List || implement IList) and check .Exists(item) in the .Add Method.
If you were to implement your own collection, you could use generic type constraints:
public class MyList<T>
where T : IMyConstraint
I have several templated objects that all implement the same interface:
I.E.
MyObject<datatype1> obj1;
MyObject<datatype2> obj2;
MyObject<datatype3> obj3;
I want to store these objects in a List... I think I would do that like this:
private List<MyObject<object>> _myList;
I then want to create a function that takes 1 parameter, being a datatype, to see if an object using that datatype exists in my list.... sorta clueless how to go about this. In Pseudo code it would be:
public bool Exist(DataType T)
{
return (does _myList contain a MyObject<T>?);
}
Some Clarification....
My interface is IMyObject<T>, my objects are MyObject<T>. I have a new class MyObjectManager which I need to have a List of MyObject<T> stored within. I need a function to check if a MyObject<T> exists in that list. The type T are datatypes which were auto-generated using T4.... POCO classes from my Entity Data Model.
You can make a generic function:
public bool Exists<T>() where T : class {
return _myList.OfType<MyObject<T>>().Any();
}
Note that this requires that you know T at compile-time.
If all you have is a System.Type object at runtime, you'll need to use reflection:
public bool Exists(Type t) {
var objectOfT = typeof(MyObject<>).MakeGenericType(t);
return _myList.Any(o => o.GetType() == objectOfT);
}
Note, however, that a List<MyObject<object>> cannot hold a MyObject<SomeType>.
You need to change the list to a List<object>, or make MyObject implement or inherit a non-generic type and make the list contain that type.
How about an extension method?
public static bool HasAny(this IEnumerable source, Type type) {
foreach (object item in source)
if (item != null && item.GetType().Equals(type))
return true;
return false;
}
Usage:
bool hasDataType1 = myList.HasAny(typeof(MyObject<datatype1>));
Note that if you don't want to have to type out typeof(...) -- i.e., if you basically want your Exist method to only care about objects of type MyObject<T>, I'd go with something like SLaks's answer:
public static bool Exist<T>(this IEnumerable source) {
return source.OfType<MyObject<T>>().Any();
}
Also, SLaks is right that you really can't have a List<MyObject<object>> that's full of anything other than objects of type MyObject<object> or some derived class (and MyObject<datatype1>, etc. do not derive from MyObject<object> -- generics don't work that way).
Another way I might suggest to work around the whole "you can't get the type of a generic class using a System.Type object without using reflection" issue would be this: Make your MyObject<T> implement a non-generic interface, like this:
public interface IMyObject {
Type DataType { get; }
}
public class MyObject<T> : IMyObject<T>, IMyObject {
public Type DataType {
get { return typeof(T); }
}
}
Then your list could be a List<IMyObject> (the non-generic interface) and your Exist method could look like this:
public static bool Exist<T>(this IEnumerable source, Type type) {
return source.OfType<IMyObject>().Any(x => x.DataType.Equals(type));
}
Since they all implement the same interface, instead of casting them to object and calling GetType (which can be expensive) why not add a property to your interface called class name (or something)? Then you can use the linq in order to grab that property. And don't forget using System.Linq
using System.Linq;
public bool Exist(List<IMyInterface> objects, IMyInterface typeToCheck)
{
return objects.Any(t => t.ObjectName == typeToCheck.ObjectName);
}