Jon Skeet said:
So that'd make it a method that stores the value in a new type, not a
property of the original type.
Patient: Doctor, it hurts when I do this (hits head)
Doctor: Well don't do that then
LOL. Weren't you complaining before about t.Sleep, and now you go and
design an even worse API, then say well don't use it that way. Great
inconsistency in your argument.
Seriously, fluent interfaces sometimes involve intermediate types which
indeed don't make sense on their own, outside the fluent interface
expression.
First, in that case those types are not a property of the original type, so
a method is more appropiate. Second it is bad desing and goe aginst
standard naming and type practices.
Second, what you are basically doing with From the types and it's Now and
Today properties is saying a Leg has a Chair and a Table and a Human
property. That's wrong.
Avoids intermediate types.
yes, when someone takes a good thing too far
uses methods
(and no intermediatry type)
Can't say I like those much personally, although the Sun/Thoughtworks
paper uses something similar.
Well they are the same as in the first and third link you provided, and they
don't suffer from the issues an intermediary type does.
The problem with the intermediary type is obvious, and you are contradicting
yourself as to your arguments over t.Sleep. Bad APi is bad API. Saying you
can only use it this way, yet exposing a type as a property and then saying
don't make a reference to that is silly.
*If* from was a method, and it was marked as must be chained or similar then
the 1.Day.From.Now might make sense. From is not a property of a timespan,
and should not be presented as such simply because you want to avoid the
()'s. And it certainly should not be able to be used unchained. I think if
you want "fluent" language constructs, you also have to have the appropriate
rules of grammar that don't allow broken sentences, and where *verbs*
(methods) are not confused with *nouns* (properties)
True. I wouldn't like to say exactly why, but it's just a gut feeling.
Again, inconsistent rules of grammar
The added item, or the collection it's been added to? The latter
allows:
x.Add(new Foo())
.Add(new Bar())
.Add(...)
in the case of Add, I would argue the item added as you often return extra
information such as index. The convention today is mroe oten than not to do
that, so returning the container would contradict existing API.
For the above example, I don't think .Add(....).Add(...) is really clear as
to whether the adding is to the item jusut added or the parent. I would
avoid this, in favour of an AddItems call.
I see your point there. An alternative in the world of immutable
objects would be to return a new object equal to the previous one
except with a different width.
Yeh you'd have to, eg: "hello".Add(" world"). ....
Now in this case, the case of an immutable object, neither the original item
or the item added are actually the return value, so you return a new object
with the value of both.
In many cases, yes - but I can imagine cases where it would be
reasonable to use properties instead.
hmmm.... i think the value of properties is definetly not in any fluent
interface. Fowler seems to agree on that. For fluent interfaces methods
make more sense, and avoid situations where a leg has a table and a chair
property
No, I'd say it has to allow the state to be mutated appropriately. It
doesn't have to expose the nature of the storage (field, database etc).
I disagree. For it to be a property extension, it needs to be backed as
such by the type being extended, otherwise it isn't a property.
I can't help it if my understanding of "underlying storage" appears to
be radically different to yours
Well you can if you try
Again, I'm sure we'll have to agree to differ. (Is anyone else reading
at this point?)
Okay, using your definition the underlying storage of the original
exposed property is the field (or whatever) then, right?
correct
I claim that
you can write an extension property without knowing or caring that the
original type happens to use a field.
huh ? Again you are going from the extension property and ***its*** backing
storage, and somehow equating that to a private field in the type being
exposed. Let me make this simple for you. Let's say you have an Int16, and
you give it an Int32Value property. As the Int16 does not provide any
storage mechanism for the entire Int32 you'll get overflow exceptions. So
the type being extending has to expose a value or values that serve as the
backing store for your extension property. This isn't rocket surgery
The original type doesn't need to
expose its underlying storage - it needs to expose a storage interface,
whether that's through properties or methods.
Right. It needs to provide the underlying storage for your extension
property.
Where you've got a particular date, certainly use that date.
The point I am making is that fluent languages
<shrugs>
If you don't want to use extension properties,
Again, fluent interfaces don't require extension properties. That doesn't
mean extension properties don't have some usage. I think the best example is
in a property set syntax. You're arguments have been read only, and fluent
interfaces, and on that I disagree. I believe the example of 1.Day.From
highlights that these should not be properties. Instead you need to be
looking at grammar rules.
I'm certainly not going
to try to twist your arm into doing so. But don't be surprised if they
appear in a future version of C# (or VB, or other languages).
Would it upset you if I told you they are in fact already in VB