var isEnum = (value ! null) && reflectClass(value.runtimeType).isEnum;
// In C#, it's so easy
// var isEnum = value is Enum;
/// Converts [input], which is an integer or a string, into an enum value of
/// type [enumType].
/// Returns `null` if fails.
parseEnum(input, Type enumType) {
try {
var values = reflectClass(enumType).getField(#values).reflectee;
if (input is int) {
return values[input];
}
for (var value in values) {
if (value.toString().split('.')[1] == input) {
return value;
}
}
} catch (e) {
}
return null;
}
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.
As far as I can see, there are two big limitations of enum at the moment.1. No easy way to know if an object is an enum (of and kind)
var isEnum = (value ! null) && reflectClass(value.runtimeType).isEnum;
// In C#, it's so easy
// var isEnum = value is Enum;
As far as I can see, there are two big limitations of enum at the moment.1. No easy way to know if an object is an enum (of and kind)
var isEnum = (value ! null) && reflectClass(value.runtimeType).isEnum;
// In C#, it's so easy
// var isEnum = value is Enum;
2. No built-in support for parsing an integer or a string into an enum value. This is how I implement my own parsing method.
/// Converts [input], which is an integer or a string, into an enum value of
/// type [enumType].
/// Returns `null` if fails.
parseEnum(input, Type enumType) {
try {
var values = reflectClass(enumType).getField(#values).reflectee;
if (input is int) {
return values[input];
}
for (var value in values) {
if (value.toString().split('.')[1] == input) {
return value;
}
}
} catch (e) {
}
return null;
}
So, will the Dart team resolve these limitations in the next version of the language?
--
On Wed, Sep 16, 2015 at 5:27 PM, Man Hoang <joll...@gmail.com> wrote:As far as I can see, there are two big limitations of enum at the moment.1. No easy way to know if an object is an enum (of and kind)
var isEnum = (value ! null) && reflectClass(value.runtimeType).isEnum;
// In C#, it's so easy
// var isEnum = value is Enum;Just for clarification: In which cases do you need to know that a value is an instance of a class created using "enum"?The interface is minuscule (.index) and the index isn't that useful if you don't know the type, and since the methods on those are static, there isn't a lot to use it for.
if (value is Enum) return value.index;
// or
if (value is Enum) return value.toString().split('.')[1];
enum Color { blue, green, red }
Color.green.toString() == 'Color.green';
// Consider adding this method.
Color.green.toSimpleString() == 'green';
// Or consider adding this getter.
Color.green.name == 'green';
2. No built-in support for parsing an integer or a string into an enum value. This is how I implement my own parsing method.
/// Converts [input], which is an integer or a string, into an enum value of
/// type [enumType].
/// Returns `null` if fails.
parseEnum(input, Type enumType) {
try {
var values = reflectClass(enumType).getField(#values).reflectee;
if (input is int) {
return values[input];
}
for (var value in values) {
if (value.toString().split('.')[1] == input) {
return value;
}
}
} catch (e) {
}
return null;
}
class TestEnum extends EnumClass {
static final
yes = new TestEnum._("yes"),
no = new TestEnum._("no"),
maybe = new TestEnum._("maybe");
TestEnum._(String name) : super(name);
}
BTW, it's not obvious that you need enums values to be "const", even with current language design. (I can't immediately find a good use case that requires constness).
BTW, it's not obvious that you need enums values to be "const", even with current language design. (I can't immediately find a good use case that requires constness).
I have tested things in Webstorm and my results are different from yours:
- I have no warning when I do not cover all enum values in a "switch" statement.
- When I try "case null" for an "int" variable in Webstorm then I get this error:
error: line 10 pos 8: expected case expression of type int
case null: print("int null");
I find it rather strange that one can assign "null" to a variable of type X but
one can not match "null" as expression of type X for a "switch" statement.
I used dartpad for my etudes, but I can't figure out which version of dart compiler is there.
All I know is that dartpad accepts the following program, no questions asked:
void main() {
int x=0;
switch (x) {
case null:
}
}
--
For other discussions, see https://groups.google.com/a/dartlang.org/
For HOWTO questions, visit http://stackoverflow.com/tags/dart
To file a bug report or feature request, go to http://www.dartbug.com/new
To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.
null
as a case
constant prevents code being written that can never be executed. If
the switch
statement's Expression is of a
reference type, that is, String
or a boxed primitive type or an enum
type, then an exception will be thrown will occur if
the Expression evaluates to null
at run
time. In the judgment of the designers of the Java programming language, this is a
better outcome than silently skipping the entire switch
statement or
choosing to execute the statements (if any) after the default
label
(if any).
Aha! Here's what happens.
This is valid:
void main() {
int x=0;
switch (x) {
case null:
}
}
But this is not:
void main() {
int x=0;
switch (x) {
case 0:
case null: // error: Case expressions must have the same types, '0' is not a 'Null'
}
}
Dart just requires that all actual "cases" to be of the same type. So "null" *alone* is treated as OK case (because there's nothing it can conflict with).
Compare with java spec (maybe written by Gilad?)
Quote:
The prohibition against usingnull
as acase
constant prevents code being written that can never be executed. If theswitch
statement's Expression is of a reference type, that is,String
or a boxed primitive type or an enum type, then an exception will be thrown will occur if the Expression evaluates tonull
at run time. In the judgment of the designers of the Java programming language, this is a better outcome than silently skipping the entireswitch
statement or choosing to execute the statements (if any) after thedefault
label (if any).
End Quote
In dart, exception is NOT thrown if Expression evaluates to null. I think it undermines the logic behind special treatment of enum in a context of switch statement.
The following is a valid dart program, it compiles and runs (in 1.12.1)
enum MyEnum {
foo
}
void main() {
MyEnum x=null;
switch (x) {
case MyEnum.foo:
}
print("OK"); // no error thrown for x=null - really prints OK
}
Requirement of "full set of enum values in switch" kind of makes sense (IMO) only if the cases really exhaust the possibilities for Expression.
If we leave a loophole for x=null, then our list of variants is not complete.
Java cleverly avoids this pitfall by throwing NPE upfront when Expression==null
Won't it be a good idea for dart to do the same?
But then, I subscribe to the idea that switch statements are symptoms of a bad OO design to begin with. You should use method dispatch instead - and enums should be able to have methods for exactly that reason. Or tables, if your values are really froma a small set of simple value.
Simple enums like what we have is just begging for switching by value, they are actively encouraging bad design.
class TestEnum extends EnumClass {
static final
yes = new TestEnum._("yes", ()=>"Mr. Yes"),
no = new TestEnum._("no", ()=>"I don't even know who I am"),
maybe = new TestEnum._("maybe", ()=>"call me 'maybe'");
Function _whoAreYou;
TestEnum._(String name, this._whoAreYou) : super(name);
String whoAreYou()=>_whoAreYou();
}
Can you give an example how a method could replace a "switch" statement ?
Maybe you want to replace this:switch (enum):by this:
case enum.A : object.someMethod();break;enum.someMethod();
Obviously what enum.someMethod() does depends on the enum and not on method that would like to call object.someMethod() and not enum.someMethod().
I do not see how one can replace "if" or "switch" by a method dispatch.
My problem is that Java enums allow you to use dispatch instead of switch by allowing you to add methods to the enum objects, and even individual methods to each object.Dart enums only support switching, which is kindof sad.
That uses method dispatch to select which code to run, like a switch does, but puts it on the objects themselves instead of in some unrelated function elsewhere.
You can't do that for integers or strings, or just classes that you're not writing yourself, which is why switching on integers may make sense (but only if you are not using the integers to represent objects - in that case you should use the object itself). A scanner is the typical example where you want to switch on an plain input code point.