What's the Java equivalent of C#'s:
enum Foo
{
Bar = 0,
Baz = 1,
Fii = 10,
}
If you want attributes for your enum you need to define it like this:
public enum Foo {
BAR (0),
BAZ (1),
FII (10);
private final int index;
Foo(int index) {
this.index = index;
}
public int index() {
return index;
}
}
You'd use it like this:
public static void main(String[] args) {
for (Foo f : Foo.values()) {
System.out.printf("%s has index %d%n", f, f.index());
}
}
The thing to realise is that enum is just a shortcut for creating a class, so you can add whatever attributes and methods you want to the class.
If you don't want to define any methods on your enum you could change the scope of the member variables and make them public, but that's not what they do in the example on the Sun website.
If you have a contiguous range of values, and all you need is the integer value, you can just declare the enum minimally:
public enum NUMBERZ {
ZERO, ONE, TWO
}
and then obtain the int value as follows:
int numberOne = NUMBERZ.ONE.ordinal();
However, if you need a discontiguous range (as in your example, where you jump from 1 to 10) then you will need to write your own enum constructor which sets your own member variable, and provide a get method for that variable, as described in the other answers here.
It is:
enum Foo
{
Bar(0),
Baz(1),
Fii(10);
private int index;
private Foo(int index) {
this.index = index;
}
}
Note that to get the value of the enum from the index, Foo.valueOf(1) (*), would not work. You need do code it yourself:
public Foo getFooFromIndex(int index) {
switch (index) {
case 0:
return Foo.Bar;
case 1:
return Foo.Baz;
case 10:
return Foo.Fii;
default:
throw new RuntimeException("Unknown index:" + index);
}
}
(*): Enum.valueOf() return the enum from a String. As such, you can get the value Bar with Foo.valueOf('Bar')
Sounds like you want something like this:
public enum Foo {
Bar(0),
Baz(1),
Fii(10);
private int number;
public Foo(int number) {
this.number = number;
}
public int getNumber() {
return number;
}
}
For starters, Sun's Java Enum Tutorial would be a great place to learn more.
public enum Foo {
Bar(0),
Baz(1),
Fii(10);
private final int someint;
Foo(int someint) {
this.someint = someint;
}
}
In Java enums are very similar to other classes but the the Java compiler knows to treat a little differently in various situations. So if you want data in them like you seem to you need to have an instance variable for the data and an appropriate constructor.
Related
I declare a variable like this:
public static int aBtn;
But the only valid values are 0,1,2,3,4 and 5
Is there any way that I can avoid any problems with my code later on my limiting it so that something like an exception will happen if I try to set the value to 6.
Note that I still want to be able to do things like:
aBtn = aBtn + 1;
No. This is a good example of why exposing public fields is a bad idea - you have no control over how they're used.
If you change it into a property, you can validate the value in the setter:
// TODO: Use a better name than either foo or aBtn
private static int foo;
public static int Foo
{
get => foo;
set => foo = value >= 0 && value < 6
? value
: throw new ArgumentOutOfRangeException("Some useful error message here");
}
If you don't like using the conditional ?: operator there, you can use a block-bodied setter:
public static int Foo
{
get => foo;
set
{
if (value < 0 || value > 5)
{
throw new ArgumentOutOfRangeException("Some useful error message");
}
foo = value;
}
}
Or better, have a utilty method that validates a value and returns the input if it's in range, or throws an exception otherwise. You can then use something like:
public static int Foo
{
get => foo;
set => foo = Preconditions.CheckArgumentRange(nameof(value), value, 0, 5);
}
Here's a slightly modified version of CheckArgumentRange from Noda Time. (The real version has a separate method to do the throwing, which I suspect is for performance reasons, to allow the comparison part to be inlined.)
internal static int CheckArgumentRange(
string paramName, int value, int minInclusive, int maxInclusive)
{
if (value < minInclusive || value > maxInclusive)
{
throw new ArgumentOutOfRangeException(paramName, value,
$"Value should be in range [{minInclusive}-{maxInclusive}]");
}
return value;
}
Couldn't you just use an enum with your only possible values? It's a good way to define small categorical sets.
For example:
public enum RangedInt
{
cero,
one,
two,
three,
four,
five,
six = 6
}
public class MyClass
{
public RangedInt Field { get; set; }
}
Sure. Use an auxiliary variable to test for the values you wish, then, if the tests go OK, pass the value to the real variable.
I think this idea is better expressed through a code. Modify it according to your wishes:
private static int aBtn;
public static int aBtnTest
{
get
{
return aBtn;
}
set
{
if ((value<0)||(value>6))) //here you test for the values you want
//do something
}
}
When you want to use your variable, you do all the processing using aBtnTest, not aBtn. By doing so, all the comparisons are made automatically by the compiler and you do not have to worry anymore about it.
This doesn't work
public class Foo {
private int X { get; }
public Foo(string s) {
int.TryParse(s, out X);
}
}
but this works:
public class Foo {
private int X { get; }
public Foo(string s) {
int x;
int.TryParse(s, out x);
X = x;
}
}
What is the difference between the two, since the out parameter doesn't need to be initialised. Why the property cannot be passed as an out parameter?
I assume this is C# 6.0 because you have a get-only property.
It doesn't work because properties cannot be passed by reference. A function that takes a ref int or an out int parameter in C# is like a function that takes an int& in C++.
But an int property is not just an int at some address. A property can run any code it wants to in both the get and the set. And the language should not treat an auto-implemented property as special.
What if I wrote code like the following?
public class Foo {
private int X {
get { return 0; }
set { }
}
public Foo(string s) {
int.TryParse(s, out X);
}
}
There simply isn't any address of an int to pass into TryParse. The rules for whether the code is allowable are not permitted to look inside the get and set implementations.
Note that this works fine:
public class Foo {
private int X;
public Foo(string s) {
int.TryParse(s, out X);
}
}
When you use out, under the hood it's really a memory address that gets passed to the function that you call. A property is not a variable but a function and you cannot take its address so a property cannot be passed in place of an out parameter.
A member variable (or local variable) occupies memory and the compiler can take their address and pass it so it works with variables but not with properties.
I'm having trouble iterating over all possible combinations of enums. I'm not too familiar with them as I've just started C# and am coming in from low level languages like C and assembler.
public enum enumA { A1, A2, A3 }
public enum enumB { B1, B2, B3 }
public class foo
{
private enumA enumAfoo;
private enumB enumBfoo;
public foo()
{
}
public foo(enumA A, enumB B)
{
enumAfoo = A;
enumBfoo = B;
}
}
public class fooTwo
{
private List<foo> allCombinations = new List<foo>();
public fooTwo()
{
}
public List<foo> GetList()
{
return allCombinations;
}
public fooTwo(bool check)
{
if (check)
{
foreach (enumA i in Enum.GetValues(typeof(enumA)))
{
foreach (enumB j in Enum.GetValues(typeof(enumB)))
{
allCombinations.Add(new foo(i, j));
}
}
}
}
}
When I run this code in a simple check output, I don't get what I'm after. Sample Main below. The output I get is just "TestingGround.foo" repeated 6 times, testing ground being my overall namespace. I Don't know if there's a problem with my logic of instantiating the list, or with how I'm converting it to string and outputting but I'd very much like some help in what's the correct procedure for doing this.
class Program
{
static void Main(string[] args)
{
fooTwo A = new fooTwo(true);
List<foo> list = A.GetList();
foreach (foo j in list)
{
Console.WriteLine(j.ToString());
}
Console.ReadKey();
}
}
ToString() returns a default representation of the object. You need to create your own ToString() method, returning what you need. For example:
public class foo
{
private enumA enumAfoo;
private enumB enumBfoo;
public foo()
{
}
public foo(enumA A, enumB B)
{
enumAfoo = A;
enumBfoo = B;
}
public override string ToString()
{
return enumAfoo.ToString() + "," + enumBfoo.ToString();
}
}
Please keep in mind that Enum has the Integer underlying value (btw, it must be unique: you can get it with simple (int) type casting). So, you are essentially have the values: 0, 1, 2 in each enum. Now, the unique combinations based on string concatenation are: 00, 01, 02, 10,11, 12, 20, 21, 22. Is it what you are looking for? Otherwise, you can apply "+" operator on underlying int values (but it will produce just 5 unique values).
Another scenario would be a concatenation of strings: you should use ToString() method in this case to get the combinations (assuming "+" operator applied to strings) of those "A1", "B1", etc. Also, you can use String.Concat(enum1, enum2) method as a shortcut; in this case you can omit the ToString()because String.Concat() will take care of proper type casting to string.
Hope this may help. Best regards,
This question already has answers here:
Is it possible to change the default value of a primitive data type?
(6 answers)
Closed 7 years ago.
I'm just curious to know, is it possible to change default value of e.g. int in C# and I can have a value -1 instead of 0.
public class Foo {
public int i;
}
...
foo = new Foo();
Console.Write(foo.i);
so this code must return
-1
Without explicit initializing
public class Foo {
public int i = -1;
}
Can I always be sure, that someone don't print somewhere something like
#define TRUE FALSE
but for default value of int
P.S. for interest purposes only.
No, basically. Assuming you don't initialize fields, the memory space is simply zeroed. You shouldn't expose fields directly anyway.
One trick I have seen to get around this (used by the capnp serializer, which works against raw memory, not objects) is to use xor. For example: if the default is -1, you can xor the value in and out:
public class Foo {
private int i;
public int I {
get { return i ^ -1; }
set { i = value ^ -1; }
}
}
This has no initialization, and does what you want. For use with types other than bools and integers this is more complex, but still possible - but it would be easier to use an initializer.
Note that for the -1 case, you could use "not" rather than "xor":
public class Foo {
private int i;
public int I {
get { return ~i; }
set { i = ~value; }
}
}
However: a field initializer (int i = -1;) or a constructor (public Foo() { i = -1; }) is probably simpler.
You can't change int's default value, but you can set Foo's variables default value:
public class Foo
{
public int i;
public Foo()
{
i = -1;
}
}
As far as I know, you can not change the default value of value types.
But you can certainly initialize it to a value you want.
for eg.
public class Foo {
public int i = -1;
}
...
foo = new Foo();
Console.Write(foo.i);
it will return
-1
A nice solution would be to override default(T), but you can't override this keyword. It is always null for reference types and zero for value types.
I have an enum and i want to "hide" one of its values (as i add it for future support).
The code is written in C#.
public enum MyEnum
{
ValueA = 0,
ValueB = 1,
Reserved
}
I don't want to allow peoples who use this code to use this values (MyEnum.Reserved).
Any idea?
TIA
You could use the 'Obsolete' attribute - semantically incorrect, but it will do what you want:
public enum MyEnum
{
ValueA = 0,
ValueB = 1,
[Obsolete("Do not use this", true)]
Reserved
}
Anyone who tries to compile using the Foo.Reserved item will get an error
If you don't want to show it, then don't include it:
public enum MyEnum
{
ValueA = 0,
ValueB = 1,
}
Note that a user of this enum can still assign any integer value to a variable declared as MyEnum:
MyEnum e = (MyEnum)2; // works!
This means that a method that accepts an enum should always validate this input before using it:
void DoIt(MyEnum e)
{
if (e != MyEnum.ValueA && e != MyEnum.ValueB)
{
throw new ArgumentException();
}
// ...
}
So, just add your value later, when you need it, and modify your methods to accept it then.
This is not possible in C#. All enum values are accessible if the Enum itself is accessible.
The only way you could simulate accomplishing this is by using a less accessible static field that used an integer value not already used in the Enum.
public enum MyEnum {
ValueA = 0;
ValueB = 1;
}
internal static class MyEnumEx {
internal static MyEnum Reserved = (MyEnum)42;
}
I'm curious though as to why you would want to do this. No matter what you do users can still provide the Reserved value. All that needs to be done is to cast an int of the appropriate value to the MyEnum type.
// Code that shouldn't access Reserve
MyEnum reserved = (MyEnum)42; // Woot!
if you want to hide from intellisense or PropertyGrid enumerated members, you can apply:
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
and
[System.ComponentModel.Browsable(false)]
Example:
public enum MyEnum
{
A,
B,
[System.ComponentModel.Browsable(false)]
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
C
}
C is not visible
You can achieve something like this by using your own custom type instead of enum:
// This type works pretty much the same way an enum works;
// each specific value can be cast to/from an int, and each has
// a specific name that is returned on calling ToString().
public sealed class MyEnum
{
private readonly int _value;
private readonly string _name;
// private constructor -- ensure that the static members you define below
// are the only MyEnum instances accessible from any outside code
private MyEnum(int value, string name)
{
_value = value;
_name = name;
}
// no need to override Equals or GetHashCode, believe it or not --
// one instance per value means we can use reference equality and
// that should be just fine
public override string ToString()
{
return _name;
}
// provide direct access only to these members
public static readonly MyEnum ValueA = new MyEnum(0, "ValueA");
public static readonly MyEnum ValueB = new MyEnum(1, "ValueB");
// this member is only available to you within the current assembly
internal static readonly MyEnum Reserved = new MyEnum(-1, "Reserved");
}
You could even further emulate the behavior of enum values by, for example, overloading the explicit operators to convert to/from MyEnum objects to int values (took JaredPar's suggestion to use this rather than implicit):
public static explicit operator MyEnum(int value)
{
switch (value)
{
case 0:
return ValueA;
case 1:
return ValueB;
default:
throw new InvalidCastException();
}
}
public static explicit operator int(MyEnum value)
{
return value._value;
}
You can't hide it, but you can add a comment that this value doesn't have any effect at this moment. Otherwise just remove it and add it if you add the support, this shouldn't break any other code dependent on it, as long as the original values don't change.
Are you using the "hidden" value internally? If not:
public enum MyEnum
{
ValueA = 0,
ValueB = 1,
//TODO: Reserved
}
You gain nothing by defining an unused variable.
one way you can do this set the value of this variable null.
so when ever its called from enum it'll b null. in short user can't access its value.
public enum MyEnum
{
ValueA = 0,
ValueB = 1,
Reserved.None
}
I had a similar problem with enum Flags, but the solution I used should work without the Flags attribute.
You can create two enum types, one for the reserved values and the other for the publicly usable values. You can use HasFlag with the reserved type without casting, but assignment requires casting.
[Flags]
public enum MyEnumReserved {
Income = 1,
Expense = 2,
Discretionary = 4,
Critical = 8
}
[Flags]
public enum MyEnum {
Income = MyEnumReserved.Income,
DiscretionaryExpense = MyEnumReserved.Expense | MyEnumReserved.Discretionary,
CriticalExpense = MyEnumReserved.Expense | MyEnumReserved.Critical
}
bool IsIncome(MyEnum val) => val.HasFlag(MyEnumReserved.Income);
...
MyEnum foo = (MyEnum)MyEnumReserved.Expense | (MyEnum)MyEnumReserved.Discretionary;