As far as I can see, there is no similar way of replicating the
following Delphi-code in C#... Is that true?
type
IntRange = -5..5;
CharRange = 'a'..'z';
TColors = (Red, White, Green, Blue, Yellow);
ColorRange = White..Blue;
Jan 9 '06
21 1964
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard .caspershouse.c om> wrote: Generics doesn't really do much here (yes, compile time checking against the type passed in is nice)
It also prevents boxing.
but I think that the thing the OP is trying to get at is that he doesn't want to perform a check manually, he wants to say somehow that this is his range, and have the runtime enforce it.
Well, I'm not sure I see much difference between:
ColorRange = White..Blue;
and
Range<Color> colorRange = new Range<Color>(Co lor.White, Color.Blue);
(I'd have expected new Range(Color.Whi te, Color.Blue) to work, but it
doesn't - I need to check the spec to see why.)
The former is certainly neater, but you still get to find out
inclusivity etc - and it probably wouldn't be too hard to give it a bit
more functionality if required.
Maybe I'm missing some more functionality - but all the examples given
can be done with the Range type I gave.
--
Jon Skeet - <sk***@pobox.co m> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jon,
I'm not an expert on Delphi, but my impression is that the OP wanted
something more. Yes, the range class does work, but that's not the point.
With context bound objects, you can do something like:
public void MyFunction([Range(0, 5)] int value)
{
// Do something with value here.
// NO need to check against range, since it will have
// already been checked by the context bound object.
}
This is a ficticuous context bound attribute, used to display the point.
This way, his function can assume the check passed, otherwise, the
interception code which the Range attribute handles would throw an
exception.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
news:MP******** *************** *@msnews.micros oft.com... Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard .caspershouse.c om> wrote: Generics doesn't really do much here (yes, compile time checking against the type passed in is nice)
It also prevents boxing.
but I think that the thing the OP is trying to get at is that he doesn't want to perform a check manually, he wants to say somehow that this is his range, and have the runtime enforce it.
Well, I'm not sure I see much difference between:
ColorRange = White..Blue; and Range<Color> colorRange = new Range<Color>(Co lor.White, Color.Blue);
(I'd have expected new Range(Color.Whi te, Color.Blue) to work, but it doesn't - I need to check the spec to see why.)
The former is certainly neater, but you still get to find out inclusivity etc - and it probably wouldn't be too hard to give it a bit more functionality if required.
Maybe I'm missing some more functionality - but all the examples given can be done with the Range type I gave.
-- Jon Skeet - <sk***@pobox.co m> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
PRECISELY!
Wouldn't it be nice to have such (easily applicable) functionality in
C#?
Nicholas Paldino [.NET/C# MVP] wrote: Jon,
I'm not an expert on Delphi, but my impression is that the OP wanted something more. Yes, the range class does work, but that's not the point.
With context bound objects, you can do something like:
public void MyFunction([Range(0, 5)] int value) { // Do something with value here. // NO need to check against range, since it will have // already been checked by the context bound object. }
This is a ficticuous context bound attribute, used to display the point. This way, his function can assume the check passed, otherwise, the interception code which the Range attribute handles would throw an exception.
-- - Nicholas Paldino [.NET/C# MVP] - mv*@spam.guard. caspershouse.co m
"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message news:MP******** *************** *@msnews.micros oft.com... Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard .caspershouse.c om> wrote: Generics doesn't really do much here (yes, compile time checking against the type passed in is nice)
It also prevents boxing.
but I think that the thing the OP is trying to get at is that he doesn't want to perform a check manually, he wants to say somehow that this is his range, and have the runtime enforce it.
Well, I'm not sure I see much difference between:
ColorRange = White..Blue; and Range<Color> colorRange = new Range<Color>(Co lor.White, Color.Blue);
(I'd have expected new Range(Color.Whi te, Color.Blue) to work, but it doesn't - I need to check the spec to see why.)
The former is certainly neater, but you still get to find out inclusivity etc - and it probably wouldn't be too hard to give it a bit more functionality if required.
Maybe I'm missing some more functionality - but all the examples given can be done with the Range type I gave.
-- Jon Skeet - <sk***@pobox.co m> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
matko,
Unfortunately, you would have to do something with ContextBoundObj ects
in order to do this. It will hinder performance, so it is not a feasibile
solution for this kind of thing (since it would be done so often).
However, if you want more information on this, check out the following
MSDN magazine article: http://msdn.microsoft.com/msdnmag/is...ContextsinNET/
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
"matko" <ma*****@gmail. com> wrote in message
news:11******** **************@ g44g2000cwa.goo glegroups.com.. . PRECISELY!
Wouldn't it be nice to have such (easily applicable) functionality in C#?
Nicholas Paldino [.NET/C# MVP] wrote: Jon,
I'm not an expert on Delphi, but my impression is that the OP wanted something more. Yes, the range class does work, but that's not the point.
With context bound objects, you can do something like:
public void MyFunction([Range(0, 5)] int value) { // Do something with value here. // NO need to check against range, since it will have // already been checked by the context bound object. }
This is a ficticuous context bound attribute, used to display the point. This way, his function can assume the check passed, otherwise, the interception code which the Range attribute handles would throw an exception.
-- - Nicholas Paldino [.NET/C# MVP] - mv*@spam.guard. caspershouse.co m
"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message news:MP******** *************** *@msnews.micros oft.com... > Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard .caspershouse.c om> wrote: >> Generics doesn't really do much here (yes, compile time checking >> against >> the type passed in is nice) > > It also prevents boxing. > >> but I think that the thing the OP is trying to >> get at is that he doesn't want to perform a check manually, he wants >> to >> say >> somehow that this is his range, and have the runtime enforce it. > > Well, I'm not sure I see much difference between: > > ColorRange = White..Blue; > and > Range<Color> colorRange = new Range<Color>(Co lor.White, Color.Blue); > > (I'd have expected new Range(Color.Whi te, Color.Blue) to work, but it > doesn't - I need to check the spec to see why.) > > The former is certainly neater, but you still get to find out > inclusivity etc - and it probably wouldn't be too hard to give it a bit > more functionality if required. > > Maybe I'm missing some more functionality - but all the examples given > can be done with the Range type I gave. > > -- > Jon Skeet - <sk***@pobox.co m> > http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet > If replying to the group, please do not mail me too
Bingo!
I want the compiler or/and the runtime-environment to detect
bounds-related errors.
That such (limited-bounds) type declaration is allowed in Delphi is
very... pleasant!
Nicholas Paldino [.NET/C# MVP] wrote: Generics doesn't really do much here (yes, compile time checking against the type passed in is nice), but I think that the thing the OP is trying to get at is that he doesn't want to perform a check manually, he wants to say somehow that this is his range, and have the runtime enforce it.
-- - Nicholas Paldino [.NET/C# MVP] - mv*@spam.guard. caspershouse.co m
"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message news:MP******** *************** *@msnews.micros oft.com... Bruce Wood <br*******@cana da.com> wrote: I don't know much about .NET 2.0 (yet), but couldn't you create an IntRange struct in .NET 1.1 that would enforce a range? It wouldn't be too difficult to do, and would incur minimum overhead.
The only downside is that you would have to declare a separate struct for each base type, and define all of the implicit and explicit casts, and math operators, etc, for the new struct.
Well... maybe I should qualify that "not too difficult to do": not too hard on the brain, but lots of typing. :-)
Here's a .NET 2.0 version (and test case). The .NET 1.1 version would either require boxing or a separate type for each enum etc:
using System;
public class Range<T> where T : struct, IComparable { T min, max;
public Range(T min, T max) { this.min = min; this.max = max; }
public bool Includes(T value) { return min.CompareTo(v alue) <= 0 && max.CompareTo(v alue) >= 0; } }
enum Foo { First, Second, Third, Fourth, Fifth }
class Test { static void Main() { Range<Foo> range = new Range<Foo>(Foo. Second, Foo.Fourth);
foreach (Foo f in Enum.GetValues( typeof(Foo))) { Console.WriteLi ne ("{0} - {1}", f, range.Includes( f)); } } }
-- Jon Skeet - <sk***@pobox.co m> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard .caspershouse.c om> wrote: Jon,
I'm not an expert on Delphi, but my impression is that the OP wanted something more. Yes, the range class does work, but that's not the point.
With context bound objects, you can do something like:
public void MyFunction([Range(0, 5)] int value) { // Do something with value here. // NO need to check against range, since it will have // already been checked by the context bound object. }
This is a ficticuous context bound attribute, used to display the point. This way, his function can assume the check passed, otherwise, the interception code which the Range attribute handles would throw an exception.
Ah, right, I'm with you. Yes, that would be handy. There are lots of
things like that which sometimes are part of design-by-contract,
sometimes part of AOP etc. Hopefully Anders is looking into those for
C# 4.0...
--
Jon Skeet - <sk***@pobox.co m> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Not from what I have seen. Anders is NOT a big fan of AOP in the least.
Method interception - MAYBE, but AOP, definitely not.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard. caspershouse.co m
"Jon Skeet [C# MVP]" <sk***@pobox.co m> wrote in message
news:MP******** *************** *@msnews.micros oft.com... Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard .caspershouse.c om> wrote: Jon,
I'm not an expert on Delphi, but my impression is that the OP wanted something more. Yes, the range class does work, but that's not the point.
With context bound objects, you can do something like:
public void MyFunction([Range(0, 5)] int value) { // Do something with value here. // NO need to check against range, since it will have // already been checked by the context bound object. }
This is a ficticuous context bound attribute, used to display the point. This way, his function can assume the check passed, otherwise, the interception code which the Range attribute handles would throw an exception.
Ah, right, I'm with you. Yes, that would be handy. There are lots of things like that which sometimes are part of design-by-contract, sometimes part of AOP etc. Hopefully Anders is looking into those for C# 4.0...
-- Jon Skeet - <sk***@pobox.co m> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet If replying to the group, please do not mail me too
Nicholas Paldino [.NET/C# MVP] <mv*@spam.guard .caspershouse.c om> wrote: Not from what I have seen. Anders is NOT a big fan of AOP in the least. Method interception - MAYBE, but AOP, definitely not.
Well, that might be due to current implementations , limitations etc. I
suspect he can see the benefits of being able to specify cross-cutting
concerns, etc, even if he's not happy with how it's all done at the
moment.
I wouldn't be surprised if something came out which at least tackled
the same kinds of issues that AOP does, even if it's not immediately
recognisable as an AOP implementation.
--
Jon Skeet - <sk***@pobox.co m> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Well, as I pointed out you _could_ create a struct to wrap another
value type and then have that struct do the bounds checking on every
assignment, because each assignment from a base type would really be an
implicit conversion operation. It would invovle significant overhead
(every assignment would really be a method call), and it would also be
a heck of a lot of code to write, as you would have to reproduce every
operator, including all implicit and explicit conversions, of the
native type in your struct wrapper.
This isn't just a Delphi thing. I remember this back in 1980 with
Pascal, so it's not as though it's some fancy new AOP-related thing.
It's probably just another of those features that Anders and the C#
team saw as offering some benefits, but not sufficient benefit to
justify adding yet more syntax to the language.
You could ask for the feature, anyway... it's been in enough other
languages (Pascal and now Delphi) that it's obviously not some flash in
the pan.
Oh, sure.
Delphi _is_, more-or-less (more more than less), Pascal.
Anyway, I'd love this to be a part of C#. It's neat and helpful
functionality.
Thanks for all comments ;)
Bruce Wood wrote: Well, as I pointed out you _could_ create a struct to wrap another value type and then have that struct do the bounds checking on every assignment, because each assignment from a base type would really be an implicit conversion operation. It would invovle significant overhead (every assignment would really be a method call), and it would also be a heck of a lot of code to write, as you would have to reproduce every operator, including all implicit and explicit conversions, of the native type in your struct wrapper.
This isn't just a Delphi thing. I remember this back in 1980 with Pascal, so it's not as though it's some fancy new AOP-related thing. It's probably just another of those features that Anders and the C# team saw as offering some benefits, but not sufficient benefit to justify adding yet more syntax to the language.
You could ask for the feature, anyway... it's been in enough other languages (Pascal and now Delphi) that it's obviously not some flash in the pan. This thread has been closed and replies have been disabled. Please start a new discussion. |