What does these generic parameter constraints mean? - c#

I'm using a method with this as the 1st parameter:
Action<IFieldsetter<Contact>>
How do I read this? Does is mean that this must be an Action object where the Action constructor is constrained to accept only something that implements IFieldsetter? And it looks like IFieldsetter itself is being constrained, but I don't understand this part at all.

It's not an actual constraint, but just the type it needs. So, that method's first parameter is an Action (i.e. delegate), which has only one parameter, and that parameter is a IFieldsetter<Contact>, whatever that means. My guess is that IFieldsetter exposes a setter and in this case it must handle the type Contact, but you should be the one who knows for real what they are and do! Post the code of this interface and this class if you need further help.
For example, if it was Action<IEnumerable<String>>, it would mean that the delegate receives a list of strings as a parameter. Here's some code:
// Your method with the *special* parameter.
private void ChrisMethod(Action<IEnumerable<String>> method)
{
string[] exampleList = { "First", "Second", "Third" };
method(exampleList);
}
// The method that can be used as parameter.
private void ParameterMethod(IEnumerable<String> list)
{
foreach(string str in list)
Console.WriteLine(str);
}
public void Main()
{
ChrisMethod(ParameterMethod);
}
A constraint on a type parameter is a different thing. You can learn more about that here.

A C# System.Action (MSDN) is a delegate object where Action<T> is the equivalent of a delegate function matching void FunctionName(T). So you can set it to a function and later on call that function.
The section generics block <Contact> applies to the IFieldsetter, so you have an Action that takes an argument of IFieldsetter<Contact>. Without knowing anything about the IFieldsetter I can't tell you what it's going to do with the Contact generic argument there.
In order to use this, you'll can have something resembling the following:
void Main()
{
FunctionThatDoesStuff(SetField);
}
void FunctionThatDoesStuff(Action<IFieldsetter<Contact>> action)
{
var setter = new IFieldsetter<Contact>();
action(setter);
}
void SetField(IFieldsetter<Contact> setter)
{
}

This is nested generic type parameter. From the outermost layer, you can see that this is an Action<T> delegate. And the delegate needs an argument of type T. In this case, T is replaced by IFieldsetter<Contact>. i.e. Action<IFieldSetter<Contact>> needs an argument of type IFieldSetter<Contact>. Now the IFieldSetter<T> interface sets a field of type T. And in this case, T is replaced by Contact so IFieldSetter<Contact> sets a field of type Contact.
Let's sum up: Action<IFieldsetter<Contact>> represents an Action delegate that needs an argument of type IFieldSetter which can set a field of type Contact. Now do you understand?

Action<IFieldsetter<Contact>> means Action delegate accepts a parameter of type that implements a generic interface IFieldsetter. suppose a class is implemented with IFieldsetter intercae with Contact as the generic parameter as shown below.
public class Test: IFieldsetter<Conatct>
{
}
Now instance of this test class can be passed as parameter to the Action deletegate.

Related

C# - Need Help Understanding the Lambda Operation and <T> [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I'm currently working on a project, and need a method to get me a variable's name. (XmlNode type). I found this solution - but I have no clue how it works. Any explanation would be helpful. Thank you!
static void Main(string[] args)
{
GetName(new { var1 });
GetName2(() => var1);
}
static string GetName<T>(T item) where T : class
{
return typeof(T).GetProperties()[0].Name;
}
static string GetName2<T>(Expression<Func<T>> expr)
{
return ((MemberExpression)expr.Body).Member.Name;
}
In particular, I don't understand why the parameter is (new {var1}) and (() => var1) when calling the methods, what <T>(T item) where T : class means, and what <T>(Expression<Func<T>> expr) means.
I did read about the lambda operation and <T>, but that doesn't really help that much.
First, the nameof operator was introduced in, I believe, c# 6. It can do what you want. You use it like this:
var myVariable = new Object();
var myVariableName = nameof(myVariable);
Now to unpack your question.
What is (new {var1})?
Here you are calling the GetName method. That method takes a single parameter. The object being passed to the method in this case is instantiated with this code: new { var1 }. Here new { var1 } is creating an anonymous type. The object being created has a single property named 'var1' whose value is the variable var1. Because a property name was not supplied the property was automatically given the same name as the variable. You could have explicitly named the property when you declared the anonymous type like this: new { var1 = var1 }. Or you could have given your property a completely different name: new { DifferentName = var1 } (but this would cause GetName to return the wrong result - see below). If you were to explicitly define these types as classes they would look something like these, respectively:
public class MyClass<T>
{
public MyClass(T property)
{
var1 = property;
}
public var1 { get; }
}
and this:
public class MyClass<T>
{
public MyClass(T property)
{
DifferentName = property;
}
public DifferentName { get; }
}
What is <T>(T item) where T : class?
The <T> in GetName<T> or GetName2<T> is a generic type parameter (generics). In this case it allows you to delay the type specification of the method parameter until the method is invoked. So if I had a method with this signature, for example, MyMethod<T>(T item) I could later call it with an int like this MyMethod<int>(2) or a string like this MyMethod<string>('some string'). Here I am explicitly specifying the type with <int> and <string>. In many cases, when the type is unambigous, you can exclude the type declaration and C# will infer it. So I could do this MyMethod('some string') and C# will be able to infer the type is string. That is what is happening here: GetName(new { var1 }). Since new { var1 } is an anonymous type there is no way to explicitly specify the type when calling GetName. But you can still call GetName with an anonymous type simply by allowing C# to infer the type.
The where T : class portion of the method signature is just a generic constraint, i.e. a constraint is being placed on the types that can be passed to this method. In this case the constraint is that T must be a class and not a value type.
How does GetName<T> work?
This function is using reflection to inspect the object that was passed to it. Here is what is going on: typeof(T) gets the type of object that was passed (remember we are passing an anonymous type), GetProperties() gets all the properties of the type - this will give you an array of PropertyInfo, [0] gives you the first property in that array (in the case where new { var1 } is passed to this method the object will only have a single property named 'var1'), and finally Name gives you the name of that property.
This method is making assumptions about the object being passed to it. Specifically that the object passed has at least 1 property and that the name of the the first property has the same name as the variable whose name we are interested in. This method is far from foolproof, it could easily be broken at runtime by passing an object with no properties, or you could get back the wrong name if you failed to pass an object that conformed to the assumptions that GetName is making.
Interestingly, GetName could have been implemented without generics like this:
static string GetName3(object item)
{
return item.GetType().GetProperties()[0].Name;
}
Perhaps the author was attempting to take advantage of at least a tiny bit of compile time checking by eliminating an entire class of objects (value types) that have no properties from being passed to the method.
What is (() => var1)?
This is an expression. This particular expression represents a function that takes no parameters () and returns an object. I know that from the method signature of GetName2:
GetName2<T>(Expression<Func<T>> expr)`
See, the expr parameter is an Expression of type Func (a function) that takes no parameters and returns a on object of type T.
How does GetName2<T>(Expression<Func<T>> expr) work?
Well... the short and probably not very accurate answer is that it is returning the right side of the expression. So you pass in () => var1 and you get back var1. Let's just leave it at that for now.
new {var1} creates an anonymous object
(() => var1) is a lambda function with no parameters shorthand for:
delegate void () { return var1;}
<T>(T item) where T : class is reflection and constraining the generic
parameter to a class. See DarkSquirrel42 answer

C# Action delegate with custom class

How does the Action delegate with custom classes work when i am not explicitly passing the input parameter type of the referenced method :
DirectMethodCall.PassMethod(x=>x.NoReturnOneParameterMethod(1));
public static void PassMethod(Action<NewClass> c)
{
NewClass op = new NewClass();
c(op);
}
Why do i need to pass the "op" to the Action delegate ?
As comments are a bit messy to post code examples, I'll continue here.
You are not repeating code, you're misunderstanding what you've actually coded. public static void PassMethod(Action<NewClass> c) means
PassMethod requires, as a parameter, a method which executes on a NewClass object.
Maybe this makes it more clear:
void Main()
{
//I am defining the implementation of a method which requires as integer as a parameter, but I don't actually invoke it, just define it.
ExecuteMethod(i => Console.WriteLine(i));
}
public static void ExecuteMethod(Action<int> method)
{
//I don't know what method does, all I know is that I am running it with the number 5.
method(5);
}
ExecuteMethod Takes a method which requires an integer. It doesn't know what the method does. All it knows is that it requires an int, and it passes it the value 5
The actual code is from the caller:
i => Console.WriteLine(i)
Here, i is set to 5, and so the result is 5 being printed to the console.
Your PassMethod is expecting a delegate which accepts one parameter of type NewClass and it calls NoReturnOneParameterMethod() with parameter 1 and has a return type of void
Action<T> means it is a delegate that takes type T as its argument and has return type of void.
See: MSDN Action

delegate contravariance (parameter compatibility)

I am looking at the C# 5 in a Nutshell text, section on Delegate Parameter Compatibility. It says
When you call a method, you can supply arguments that have more specific types than the parameters of that method. This is ordinary polymorphic behavior. For exactly the same reason, a delegate can have more specific parameter types than its method target. This is called contravariance.
This paragraph makes sense up until the last sentense. Why is it contravariance, i.e. what projection here is contravariant?
The accompanying example is below.
delegate void StringAction (string s);
class Test
{
static void Main()
{
StringAction sa = new StringAction (ActOnObject);
sa ("hello");
}
static void ActOnObject (object o)
{
Console.WriteLine (o); // hello
}
}
The projection of object (the parameter of the function ActionObject) to the type declared for the delegate (string) is contravariant.
This is allowed because by passing it a string (which you must due to the delegate signature), you are guaranteed that you will have an object (which the assigned function takes), so everything is nice and safe.
Just so you know, "ordinary polymorphism" in this context is actually called covariance.
See MSDN for more details.
Function types are contravariant in argument types. In your example the type
delegate void ObjectAction(object o);
is a subtype of
delegate void StringAction(string s);
since ObjectAction can be used everywhere that StringAction is used because, if a caller is passing in a string argument, the argument must also be of type object.
object is a supertype of string but ObjectAction is a subtype of StringAction; the subtyping goes in the opposite direction. This is why it's called contravariant. Because the variation in the function subtypes goes in the opposite direction of the parameter subtypes.

Dynamically pass class and method names to a method using generics

I want to pass in dynamically a class name and a method name to a method and keep this dynamic, I'm understanding that I should use generics and possible constraints.
Example, I have a class
MemberRequestDTO (contains several properties)
I also that a Method called
RecordsToRetrieve
Using some reflection I was wanting to dynamically get the values of the properties, which I figured out how to do that, but then I realized that is is too hard code and tightly coupled of which I figured time to refactor and create a method with a signature that uses generics with constraints. having trouble with understand the use of and the constraints etc..
So I want to pass in a class name and be able to use it in the method, with reflection I plan to use it like:
Type type = typeof(classname);
I started reading and researching and I start playing with code like this:
public void GetTypeValues<T>() where T : class , new()
How do I pass in the class name of MemberRequestDTO?
What does the Generic new for me?
How do I pass a class name into the parens ()?
If I use does it also get pass into parens?
How can I pass in class and method?
Reading the above "Where T has the constraints (enforced) to be of type "class AND new() ?
A little lost and confused on this, forgive me.
EDIT:
Based on the answers and some research, I'm understanding this a bit more:
Lets forget about me trying to pass in a method, say I just want to pass in a class
Say the class with properties looks like this
public class MemberRequestDTO
{
public DateTime DateRequested { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Then I will New this up
var memberRequestDTO = new MemberRequestDTO();
Then I want to pass this to class into a method that is generic
How do I go about passing an instance of a object into a generic method? What about the signature , example public void GetTypeValues() where T : class , new()
Would I want to have the contraints of class and new() ?
For the above, is T the instance of the class? Thus the purpose is that I can be
Saying
GetTypeValues(memberRequestDTO)
( this is my actual question , pass into whatever class I instantiated and that let the method "handle" dealing with that class with looping through the properties and getting me the name values of the properties dynamically and yes it probably will not remain a void method )
Should passing in memberRequestDTO be with quotes or without? I want to be able to pass in any instance of a class to the member to then manipulate it more. () should T be there ? should the parens () be empty or contain an generic parameter for the class object ?
Here are your answers:
GetTypeValues<MemberRequestDTO>()
new() is a constraint for the Type Parameter - T. It says that the type argument T must have a public parameterless constructor. In your case, MemberRequestDTO class must a public parameterless constructor like below:
public class MemberRequestDTO
{
public MemberRequestDTO() { ... }
}
As a class name is of reference type, you can pass it as a type into the parens like: SomeMethod(typeof(MemberRequestDTO)); where the signature of the method be void SomeMethod(Type type) { }
If you pass the class as a type parameter as in point (1), it does not get passed into the parens()
class constraint implies that "The type argument must be a reference type; this applies also to any class, interface, delegate, or array type."
and new() constraint implies that "The type argument must have a public parameterless constructor. When used together with other constraints, the new() constraint must be specified last."
EDIT:
If I catch your point, then the generic method definition would be something like:
public void GetTypeValues<T>(T typeObject) where T : class
{
// typeObject specific operations
}
That uses typeObject dynamically, getting the "execution-time compiler" to perform type inference to work out T. See the reference here. Moreover, imho, you don't need the new () constraint on T here.
After that, you can pass an instance of any class to this method like below:
var memberRequestDTO = new MemberRequestDTO();
GetTypeValues((dynamic) memberRequestDTO);
EDIT 2:
USAGE: Get Type Values dynamically using Reflection
This method returns the property values wrapping into IEnumerable<KeyValuePair<string, object>>.
public static IEnumerable<KeyValuePair<string, object>> GetTypeValues<T>(T typeObject) where T : class
{
// typeObject specific operations
IEnumerable<KeyValuePair<string, object>> typeValues =
typeObject
.GetType()
.GetProperties()
.Select(property => new KeyValuePair<string, object>(property.Name, property.GetValue(typeObject)));
return typeValues;
}
How do I pass in the class name of MemberRequestDTO ?
You already have one. In a generic method "Type parameter" in this case T will be the name of type you're interested in.
public void GetTypeValues<T>() where T : class , new()
{
string typeName = typeof(T).Name;
}
What does the Generic new for me?
It is a contraint which will prevent you to pass any type without public parameterless constructor. In other words it will allow you to new up type passed in as "Type parameter"
public void GetTypeValues<T>() where T : class , new()
{
T instance = new T();//This is not possible without new constraint
}
How do I pass a class name into the parens () ?
If I use does it also get pass into parens?
Not sure what is that parens() Need more info to answer this.
How can I pass in class and method?
If I understand correctly "Type parameter" T is the runtime type which you use. So you get a Type there. Am not sure about what you mean by class? Class cannot be passed only instances can be passed.
For methods there are number of ways. You can pass MethodInfo or method name or A delegate, or a MethodCallExpression etc.
Reading the above "Where T has the constraints (enforced) to be of
type "class AND new() ?
Yes. class constraint prevents you from passing value types, new() constraint allows you to new up things.
Read more about generics here and here
I'm a little confused about what you want to do but I'll give it a shot. I can see two possible interpretations and they differ on what the caller is starting with and what you're trying to achieve.
Interpretation #1: The caller starts out knowing the name of the class and the name of the method it wants to invoke later, using an object it has in hand. This can be achieved as follows:
public Func<object, object> RecordMethod(string typeName, string methodName)
{
var type = Type.GetType(typeName);
var method = type.GetMethod(methodName);
return (object o) => method.Invoke(o, new object[0]);
}
var method = RecordMethod("MemberRequestDTO", "RecordsToRetrieve");
// later that day ...
MemberRequestDTO someObj = ...;
var result = method.Invoke(someObj);
This is fine if you need to work with type names and method names dynamically, e.g. from user input. Note that this approach requires the use of object throughout, and will only work with a method that takes no parameters. Also note that in this way the type cannot be guaranteed to have a no-arg constructor, so the caller must provide the object himself.
Interpretation #2: The caller starts out knowing the actual class and the actual method it wants to invoke later, using an object that can be constructed later. This can be achieved as follows:
public Func<TOutput> CaptureMethod<TInput, TOutput>(Func<TInput, TOutput> method)
where TInput : new()
{
return () =>
{
var source = new TInput();
return method(source);
};
}
var capturedMethod = (MemberRequestDTO dto) => dto.RecordsToRetrieve();
// later that day ...
var result = capturedMethod();
This captures a known method and returns a function which, when invoked, will instantiate your class and call the method on it. This is a more static approach (the caller knows more than in the previous example) and is able to enforce a constraint that the type being worked with must have a no-arg constructor.
I don't know if I've answered your question but this should at least give you some ideas.

C# infer Type from Generic with constraint

I'm trying to register a generic that derives from a base class in the following way, but getting the error :
cannot convert MyCallback<T> expression to type MyCallback<Event>
I was hoping the constraints would make this possible but am I missing something?
public class Event
{ };
public delegate void MyCallback<T>(T arg1) where T : Event;
static class EventDispatcher
{
public static Dictionary<string, MyCallback<Event>> eventTable = new Dictionary<string, MyCallback<Event>>();
static void RegisterCallback<T>(MyCallback<T> callback) where T : Event
{
eventTable.Add("test", callback);
}
}
When you have a MyCallback<Event> you're saying that you have a method that can take any type of event. It can accept an EventOne, or an EventTwo, or a SomeOtherEvent.
Let's say I call RegisterCallback and pass in a delegate pointing to a method with this signature:
public static void Foo(SomeOtherEvent arg)
If your code would work, and I could assign that to a MyCallback<Event>, then I could pass in an EventOne instance to that method when calling it. That's obviously a problem.
There's a term for that; you're expecting MyCallback to be covariant with respect to it's generic argument. In fact, it's contravariant. If I have a method that can accept any type of event, I can clearly pass in a SomeEvent, or a SomeOtherEvent, meaning I could assign a MyCallback<Event> to a MyCallback<SomeOtherEvent>, rather than the other way around.
If you want to tell the compiler that, "I know that this method cannot actually be called with any type of event, but I want you to allow this check and only fail at runtime if the given argument is not of the proper type." then you can do that, assuming you actually have a way of ensuring you call each callback with the proper arguments. You can't just do a cast either; you need to wrap the method in a new method that does the cast:
eventTable.Add("test", e => callback((T)e));
You need to have the type parameter be part of the EventDispatcher class:
public class EventDispatcher<T> : where T : Event {
public Dictionary<string, MyCallback<T>> eventTable = new Dictionary<string, MyCallback<T>>();
void RegisterCallback(MyCallback<T> callback) {
eventTable.Add("test", callback);
}
}
This is because the MyCallback<Event> declared in eventTable is not going to be compiled into the same type declared in RegisteredCallback when written like your example.

Categories

Resources