I'm working on a binary search algorithm, which has the following parameters:
Now when I pass these arguments:
It says that type int cannot be used as a parameter F (I was under the impression that the generic types are not concerned with types that are being passed) and that there are no 'boxing' conversion from int to IComparable.
What I was trying to do: Basically, I wanted this method to accept search key's which can be of various numeric types (ints, doubles etc.) and so in the generic method I tried to declare two types.
About this code:
The func delegate represents an object's property i.e. car.Name (string), car.Wheels(int) which are of different types. I Sort of want the key data type somehow be inferred based on the propertyFields type that's being passed, but that seems way too complicated, so I tried making it so that the F Key accepts various types and just make sure that I'm passing the correct types to it.
I don't know if this all sounds confusing, but if you have questions about any of my code, feel free to ask.
Edit: The error occurs when I call the BinarySearch Method.
Edit 2: for the propertyField i pass this as an argument: c => c.Longitude (or any other object property).
Either your 2nd constraint needs to be where F : IComparable<F> or you should not have a F at all and you should be taking in a T Key instead of a F Key
Related
I have a class that will require a varying number of Func delegates to be passed in the contructor. Each of these delegates will point to a different function, each with a different return type, and with a varying number of parameters (of type double). Each of these functions will then be called accordingly.
Question 1. Right now, to make things easier for those using this class, I am thinking about allowing the user to pass a List<object> of Func delegates. Is this possible, and if so am I able to determine the return type and number of params required for each Func in the method in which the List<object> is passed to (i.e. the constructor) ?
Question 2. If the above is not feasible, will I need to overload the constructor with every different combination of return types/number of params and route each Func accordingly -_- ... if not can someone point me in the right direction, I feel like i'm approaching this in the wrong way ...
note - coming from a python background, I would do something like this (i'm inexperienced in c#):
import inspect
def test(x): return x
inspect.getargspec(test)
returns: ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)
Many thanks
Question 1. Right now, to make things easier for those using this class, I am thinking about allowing the user to pass a List of Func delegates. Is this possible, and if so am I able to determine the return type and number of params required for each Func in the method in which the List is passed to (i.e. the constructor) ?
Not really. You could allow a List<Delegate> (or some other collection with an element type of Delegate), but nothing Func-specific, for two reasons:
Func is effectively a family of types, with different number of generic type parameters. These types are entirely separate as far as the CLR is concerned; Func<TResult> and Func<T, TResult> are as different as Action<T> and EventHandler.
Even if you were only dealing with several values of the same generic type of delegate, the fact that they could have different type arguments means they're different types to the CLR; there's no way of saying List<Func<>> for "a list of functions with potentially varying type arguments". Again, the CLR treats them as separate types - although this time at least one with a common generic type definition.
Question 2. If the above is not feasible, will I need to overload the constructor with every different combination of return types/number of params and route each Func accordingly
Well, there are several options:
Make all the parameters optional, giving each of them a default value of null, then use named arguments when calling the constructor:
var foo = new Foo(clickHandler: () => ...,
keyHandler: key => ...);
Create a builder, so that the various functions can be set as properties - this works very well with the object initializer syntax:
var foo = new Foo.Builder {
ClickHandler = () => ...,
KeyHandler = () => ...
}.Build();
Both of the latter solutions depends on you really having a specific named purpose, of course.
It would help if you could be clearer about what you're trying to achieve - as dtb says, polymorphism may be a better fit here. You could create an abstract class with no-op implementations of virtual methods, and implementations could choose which ones to override.
This question already has answers here:
What are generics in C#? [closed]
(3 answers)
Closed 5 years ago.
I know many programming and scripting languages, but I never saw something like this before:
camera = GetComponentInParent<Camera>();
Is this normal in C#? Why don't we have to pass the parameter Camera like this:
camera = GetComponentInParent(Camera);
Where can I inform myself about why it is like this?
The parameter in the first version is a type parameter. Type parameters do not refer to values, but to types. This is used in generic methods and classes, that allow (a certain) flexibility of the types used in the class, while staying statically typed.
Compare the generic list class List<T>. You have to pass a type parameter to enforce that you can't add instances of other types.
List<int> myList = new List<int>();
myList.Add(1);
myList.Add(2);
foreach(var item in myList)
{
// ...
}
Since myList has the type parameter int you and the compiler (and intellisense) know, that everything in myList is an int. Hence item will have the type int. On the other hand the following is not possible
myList.Add("FooBar");
since List<T>.Add has the signature void Add(T item) and creating a List<int> fixes the typeparameter T to int.
The second syntax
If Camera is a type this syntax is no valid C#. The compiler will throw the error
Camera is a type, which is not valid in the current context.
If GetComponentInParent would take a Type parameter (a parameter of the type Type, not a generic type parameter) you could call it like
GetComponentInParent(typeof(Camera))
but you will lose the merits of generics, i.e. the return type of GetComponentInParent won't be a Camera, but a less specialized type. If the components that can be returned by GetComponentInParent have no common ancestor, it might even return an object, whereas the generic version might have the signature
T GetComponentInParent<T>()
ich which case it would return the right type out of the box without the need to cast the result.
The argument inside the angle brackets is a type argument used for what is called "generics". The GetComponentsInParent method uses the C# generics functionality to have a different return type based on the generic type argument. You likely use this concept often without thinking too much about it when you are using lists. If I have a list of Camera objects, the way that I will create it is to say var cameras = new List<Camera>(); as opposed to var cameras = new List(Camera);.
The GetComponentsInParent method has a signature of T[] GetComponentsInParent<T>(). If is was to take a type in the parameter list instead of using generics, the signature would have to be object[] GetComponentsInParent(type T) or may GameObject[] GetComponentsInParent(type T) and it would be your code's responsibility to cast the returned array elements into the object that you actually need. Generics help us make these scenarios much cleaner.
For more information on generic types in C#, see https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/
I have a class with a bunch of methods in it, the methods transfer variables elsewhere in my program when called. I want to use a dictionary as the middle man between the methods that transfer data and the methods that call them.
So here is my question. Say I make a dictionary, where the key is an int and I want the value to be the name of a method. I will assign a new value / method each time I add to the dictionary. Is there a value type I can put there that will let me do this?
Dictionary<int, ?> methodKey= new Dictionary<int, ?>();
I tried to find a list of types that dictionary will take but I couldn't find anything specific.
Thanks in advance
Use any delegate type as a type of value. For example:
Dictionary<int, Action>
So, you'll be able to write such things:
dictionary[0] = () => Console.WriteLine("0");
dictionary[1] = Foo;
dictionary[2] = a.Bar;
Specific delegate type depends on your needs - may be, you want for methods to have some input parameters or output/return values, but it should be most common type.
Will all the methods have the same signature? If so you can probably use one of the existing Action or Func delegate, (or you can create a delegate type with that signature), and use that as your second type parameter.
If not, you can use Delegate (or even object) and cast to the appropriate type when you invoke the delegates.
I have a class that will require a varying number of Func delegates to be passed in the contructor. Each of these delegates will point to a different function, each with a different return type, and with a varying number of parameters (of type double). Each of these functions will then be called accordingly.
Question 1. Right now, to make things easier for those using this class, I am thinking about allowing the user to pass a List<object> of Func delegates. Is this possible, and if so am I able to determine the return type and number of params required for each Func in the method in which the List<object> is passed to (i.e. the constructor) ?
Question 2. If the above is not feasible, will I need to overload the constructor with every different combination of return types/number of params and route each Func accordingly -_- ... if not can someone point me in the right direction, I feel like i'm approaching this in the wrong way ...
note - coming from a python background, I would do something like this (i'm inexperienced in c#):
import inspect
def test(x): return x
inspect.getargspec(test)
returns: ArgSpec(args=['x'], varargs=None, keywords=None, defaults=None)
Many thanks
Question 1. Right now, to make things easier for those using this class, I am thinking about allowing the user to pass a List of Func delegates. Is this possible, and if so am I able to determine the return type and number of params required for each Func in the method in which the List is passed to (i.e. the constructor) ?
Not really. You could allow a List<Delegate> (or some other collection with an element type of Delegate), but nothing Func-specific, for two reasons:
Func is effectively a family of types, with different number of generic type parameters. These types are entirely separate as far as the CLR is concerned; Func<TResult> and Func<T, TResult> are as different as Action<T> and EventHandler.
Even if you were only dealing with several values of the same generic type of delegate, the fact that they could have different type arguments means they're different types to the CLR; there's no way of saying List<Func<>> for "a list of functions with potentially varying type arguments". Again, the CLR treats them as separate types - although this time at least one with a common generic type definition.
Question 2. If the above is not feasible, will I need to overload the constructor with every different combination of return types/number of params and route each Func accordingly
Well, there are several options:
Make all the parameters optional, giving each of them a default value of null, then use named arguments when calling the constructor:
var foo = new Foo(clickHandler: () => ...,
keyHandler: key => ...);
Create a builder, so that the various functions can be set as properties - this works very well with the object initializer syntax:
var foo = new Foo.Builder {
ClickHandler = () => ...,
KeyHandler = () => ...
}.Build();
Both of the latter solutions depends on you really having a specific named purpose, of course.
It would help if you could be clearer about what you're trying to achieve - as dtb says, polymorphism may be a better fit here. You could create an abstract class with no-op implementations of virtual methods, and implementations could choose which ones to override.
First let me say, that what I want to do is get the value of a property in a generic class that may be overriden by class that inherits from it. Think of it in the base class as a default value, that the inheritor of the class can override to set their own Default value.
I have tried to use reflection directly on the type, using the System.Reflection.FieldInfo.GetValue but this does not work for classes with generic types. So I think that I need to instantiate the class to be able to see what the value is.
The "types" I have I retrieved by reading the Dlls in the bin and using Reflection to find the types that inherit from my interface.
I am using .NET 4.5
here is documentation that seems like it explains exactly what I need to do
http://msdn.microsoft.com/en-us/library/b8ytshk6.aspx
In this documentation the only difference I can see is how we got our types, I looked in the bin for types and they simply called typeof(), Since types are so complex it seems this may be a likely mis-match but I cannot see what is missing(if anything)
foreach (var item in types)
{
var ts = item.GetField("DefaultTimeToExpire");
Type[] typeArguments = item.GetGenericArguments();
if (ts != null)
{
var t = item.MakeGenericType(typeArguments);
var obj = Activator.CreateInstance(t);
var timespan = obj.DefaultTimeToExpire;
subscriberInfos.Add(new Tuple<string, Type, TimeSpan>(item.Name, item, timespan));
}
}
I am calling GetField to look for Items that have a field "DefaultTimeToExpire" so far this part works well to find the type I need.
Next I call GetGenericArguments which returns an expected array of the type Arguments.
then I call MakeGenericType
and finally Create instance wich gives me the error message
"Cannot create an instance of BusinessLogic.TestSubscriberXXX`1[Message] because Type.ContainsGenericParameters is true."
This looks like exactly what I am supposed to do.
Thanks
In order to instantiate a generic type, you need to know the actual values (types) that should be substituted for its type parameters. The GetGenericArguments() method, being a form of reflection, only gives you the type arguments, not their actual values. The values are up to you... that is the entire point of generics.
If item is a type like List<T> then item.GetGenericArguments() will return an array containing a fake "type" representing the type parameter T (with its IsGenericParameter property set to true). Therefore, passing that parameter type back into item.MakeGenericType() will simply create another open generic type equivalent to the original. To close the generic type so that it can be instantiated you need to provide an actual (non-parameter) type argument, such as int.
For example, typeof(List<>).MakeGenericType(typeof(int)) will return typeof(List<int>), while typeof(List<>).MakeGenericType(typeof(List<>).GetGenericArguments()) will simply return typeof(List<>) again. This is what is happening in your code.
I'm sorry if that is a bit opaque, I don't know how else to explain it. The bottom line is that a type like List<T> is only useful if you have a type you want to substitute in place of T.