1

While trying to understand TextBoxFor() I came across this definition in MSDN....

TextBoxFor<TModel, TProperty>(HtmlHelper<TModel>, Expression<Func<TModel, TProperty>>, IDictionary<String, Object>)

Is this just a generic class, or is it somethign else, or is it non-c# ?

(The angular brackets within angular brackets is throwing me of)

And how do you interpret it (a link would be fine - as long as its ok for beginners to C# etc).

spiderplant0
  • 3,872
  • 12
  • 52
  • 91
  • John Laffoon posted this and then deleted it but I thought it was good so I will repost [generics](http://msdn.microsoft.com/en-us/library/512aeb7t.aspx) – user1477388 Aug 05 '13 at 15:17
  • Thanks user1477388, this explins generics but I cant find where it explains the dbl generics – spiderplant0 Aug 05 '13 at 15:23
  • Check this out see if it helps. I think the first answer explains pretty clearly what `Func` is used for http://stackoverflow.com/questions/4244669/expressionfunctmodel-tproperty-as-property-for-object-initialization – user1477388 Aug 05 '13 at 15:27

4 Answers4

3

This is an example of nested generic type parameters.

Expression<T> is an open generic class that takes a single type parameter.

Func<TModel, TProperty> is a concrete generic delegate type that references type parameters from the surrounding generic function.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Is there a difference if I use `Expression` or could I also use `Expression`? Do these do the same thing? Thanks. – user1477388 Aug 05 '13 at 15:22
  • Thanks @Slaks, but I dont understand what 'concrete generic delegate type that references type parameters from the surrounding generic function' means. I'm looking more for an explanation rather than a definition (i dont mean to be rude) – spiderplant0 Aug 05 '13 at 15:24
2

It's just a nested generic type.

An Expression of type Func of type TModel, TProperty

Faust
  • 15,130
  • 9
  • 54
  • 111
2

It's a class.

Expression<Func<TModel, TProperty>> encapsulates Func<TModel, TProperty>, and contains extra metadata which can be used by third parties to rebuild the Func in their own native language.

Func<TSrc, TDest> represents a function that takes TSrc as its input, and generates an instance of TDest as its output. For example, I can say:

var addOne = new Func<int, int>(i => i + 1);

and addOne would be a mapping that takes an integer and gives back that integer plus one. After you've defined it, you can then call addOne(1), and you'd expect that to give you 2.

The thing inside the brackets -- the i => i + 1 -- is a piece of syntax called a lambda. Confusingly, a lambda can be used to represent both a Func<TSrc, TDest> and an Expression<Func<TSrc, TDest>>. That is, depending on the context,

i => i + 1

represents either a Func<int, int> object or an Expression<Func<int, int>> object. This is an example (my favourite example) of homoiconicity in a language. That is, a syntax in which you can have objects of different classes represented by the same symbol, or icon.

Going back to MVC, the reason it wants an Expression<Func<TModel, TProperty>> rather than just a plan old Func<TModel, TProperty> is because it wants to know more about the property than what that property does with the model instance: it wants to know extra data such as the property name, its attributes, and what kind of error handling it uses. So you can give it something like

@Html.TextBoxFor(m => m.FirstName, ...)

and MVC will look up the property FirstName in your model and build up all sorts of HTML based on the attributes you've defined on that property.

That's more or less how it works.

Rob Lyndon
  • 12,089
  • 5
  • 49
  • 74
  • Thanks do you have a link that would explain how this all works.? Or if you can tell me what I should type into google? – spiderplant0 Aug 05 '13 at 15:26
  • Sure. There's a question about it here. http://stackoverflow.com/questions/793571/why-would-you-use-expressionfunct-rather-than-funct. If you Google "Expression Func", you'll fund some links -- or "Expression Func Lambda". – Rob Lyndon Aug 05 '13 at 15:36
  • I've added a few more lines of explanation myself. Let me know if it seems like double dutch. – Rob Lyndon Aug 05 '13 at 15:52
1

A class with nested generic type parameters.

The inner part:

Func<TModel, TProperty>

A delegate, referencing ("describing") a function that takes the generic type TModel as an argument and returns a result of generic type TProperty, e.g.:

TProperty MyFunc(TModel model)

... which corresponds to the types in the usual argument to TextBoxFor():

model => model.Name

model is of type TModel and model.Name is of type TProperty.

The outer part:

Expression<T>

An expression tree describing a lambda expression (delegate) of the type T. The Expression<T> generic class allows you to (in simplified terms) examine the code itself at runtime rather than the result of executing it. In other words, the TextBoxFor() method can e.g. extract the actual name of the property (Name in the above example), in addition to compiling the expression and executing it to get the result.

If we simply took a Func<> as an argument, we would only be able to call the passed delegate and get the result of that call, rather than examining it in this kind of detail.

For the HTML helpers, the use of expression trees is mainly a type safe alternative to the TextBox() methods, which take the name of the property as a string.

So, in combination:

Expression<Func<TModel, TProperty>>

A parameter to TextBoxFor() that is "An expression tree describing: a lambda expression that takes a parameter of the generic type TModel and returns a property of the generic type TProperty".

The nested generics aren't limited to something as relatively advanced as expression trees. A simpler, concrete, example of nested generics is this:

Dictionary<string, List<int>>

A dictionary with strings for keys, and Lists of ints as values.

JimmiTh
  • 7,389
  • 3
  • 34
  • 50