am using generated protobuf code (see http://code.google.com/p/protobuf/)
I have a generated class looks like this :
public class Fruits{
private int _ID_BANANA = (int)1;
private int _ID_APPLE = (int)2;
public int ID_BANANA
{
get { return _ID_BANANA; }
set { _ID_BANANA = value; }
}
public int ID_APPLE
{
get { return _ID_APPLE; }
set { _ID_APPLE = value; }
}
}
Then they are constant values but I can't use then as such in my code.
For example I want to do a mapper like this :
public static Color GetColor(int idFruit) {
switch (idFruit)
{
case new Fruits().ID_BANANA:
return Color.Yellow;
case new Fruits().ID_APPLE:
return Color.Green;
default:
return Color.White;
}
}
I have the error : a constant value is expected.
I thougth about creating an enum, but seems to be the wrong way, tryed something like :
public const int AppleId = new Fruits().ID_APPLE;
Not working either...
Someone have an idea?
Why not to use if else if statements here?
var fruits = new Fruits();
if (idFruit == fruits._ID_BANANA)
return Color.Yellow;
else if (idFruit == fruits._ID_APPLE)
return Color.Green;
else
return Color.White;
Or dictionary:
this.fruitsColorMap = new Dictionary<int, Color>
{
{ fruits._ID_BANANA, Color },
{ fruits._ID_APPLE, Green }
};
And then:
public static Color GetColor(int idFruit) {
if (this.fruitsColorMap.ContainsKey(idFruit) {
return this.fruitsColorMap[idFruit];
}
return Color.White;
}
The case values in a switch statement have to be constants - that's part of the switch statement's definition:
switch (expression)
{
case constant-expression:
statement
jump-statement
[default:
statement
jump-statement]
}
as per the switch (C#) documentation from Microsoft.
you will notice the constant-expression bit. That means that it can be determined at compile time. So calls to functions (and a reference to a property property is really a function call in disguise) are not allowed here.
Related
I have a simple struct that looks like this:
public struct GridNeighbours
{
public static Vector2Int North = new Vector2Int(0, 1);
public static Vector2Int South = new Vector2Int(0, -1);
public static Vector2Int East = new Vector2Int(1, 0);
public static Vector2Int West = new Vector2Int(-1, 0);
}
Is there a way to "iterate" through each of these fields somehow with a for loop? Do structs by chance index their fields or something? It would make my code a lot cleaner if it was possible but I am not sure how to make it iterative.
Edit: due to this being used in a hot path in a game, is there a way to rewrite this so i can avoid reflection ?
This is not a duplicate since i need an alternative approach to avoid reflection.
public struct GridNeighbours {
public enum Cardinal { North, East, South, West }
public static Vector2Int[] Neighbours = { new Vector2Int(0, 1), new Vector2Int(1, 0), new Vector2Int(0, -1), new Vector2Int(-1, 0) };
public Vector2Int this[Cardinal dirn] {
get { return this[(int)dirn]; }
set { this[(int)dirn] = value; }
}
public Vector2Int this[int dirn] {
get { return Neighbours[dirn]; }
set { Neighbours[dirn] = value; }
}
}
Example use:
var cell = new GridNeighbours();
var NorthNeighbour = cell[Cardinal.North];
Assert(cell[Cardinal.South] == cell[2]); // This is true!
===
Alternatively, if you want "direct" properties:
public struct GridNeighbours {
public enum Cardinal { North, East, South, West }
public static Vector2Int[] Neighbours = { new Vector2Int(0, 1), new Vector2Int(1, 0), new Vector2Int(0, -1), new Vector2Int(-1, 0) };
public static Vector2Int North { get { return Neighbours[0]; } set { Neighbours[0] = value; } }
public static Vector2Int East { get { return Neighbours[1]; } set { Neighbours[1] = value; } }
public static Vector2Int South { get { return Neighbours[2]; } set { Neighbours[2] = value; } }
public static Vector2Int West { get { return Neighbours[3]; } set { Neighbours[3] = value; } }
}
Without using reflection I don't think you can do it given the signature you have there.
What you could do is to setup an indexer on the struct that would allow you to loop.
If you mean the possible values in the struct will not be known in the compile-time, then you can try using Reflection. More specifically, using Type.GetFields() or Type.GetProperties().
Example:
Type structType = typeof(GridNeighbours);
FieldInfo[] fields = structType.GetFields();
Foreach(FieldInfo field in fields)
{
//Do something
}
But keeping the fact in mind that there will always be four directions, why a simple GridNeighboursInstance.North is not a preference for you.
If you don't want to use a dynamic way so I can suggest you to use a static way! When you have only those four members and you want to iterate over them you need to implement an AsEnumerable method inside your struct something like this:
public static IEnumerable<Vector2Int> AsEnumerable()
{
for (var i = 0; i < 4; i++)
{
switch (i)
{
case 1:
yield return North;
break;
case 2:
yield return South;
break;
case 3:
yield return East;
break;
case 4:
yield return West;
break;
}
}
}
I think there are some better way, But HTH ;).
i have declared 2 string values eg: ChName1, ChName2 and 2 int values eg: Delay1, Delay2 in the settings.
i would like to implement an array in class so life will be more easier. can somebody correct my code with necessary explanations
public class GetDefaultValues
{
public string Name[int i]
{
get
{
switch (i)
{
case 0:
return Name.Properties.Settings.Default.ChName1;
case 1:
return Name.Properties.Settings.Default.ChName2;
default:
return "Not Implemented";
}
}
set
{
switch (i)
{
case 0:
{
Name.Properties.Settings.Default.ChName1 = value;
break;
}
case 1:
{
Name.Properties.Settings.Default.ChName2 = value;
break;
}
}
Name.Properties.Settings.Default.Save();
}
}
public int Value[int i]
{
get
{
switch (i)
{
case 0:
return Name.Properties.Settings.Default.Delay1;
case 1:
return Name.Properties.Settings.Default.Delay2;
default:
return 0;
}
}
set
{
switch (i)
{
case 0:
{
Name.Properties.Settings.Default.Delay1 = value;
break;
}
case 1:
{
Name.Properties.Settings.Default.Delay2 = value;
break;
}
}
Name.Properties.Settings.Default.Save();
}
}
}
then in my main code i could do like this
GetDefaultValues Vlues = new GetDefaultValues();
Vlues.Name[0] = "SomeName";
string SomeString = Vlues.Name[1];
Vlues.Value[0] = 125;
int SomeInt = Vlues.Value[1];
this code is generating errors in my code.
Error 2 Bad array declarator: To declare a managed array the rank
specifier precedes the variable's identifier. To declare a fixed size
buffer field, use the fixed keyword before the field type
will be happy if i could know why??
please help!!
I would recommend not to use properties for this because properties should not have that logic. You should use methods instead.
This could be look like this for example (just added the name as a sample).
public class GetDefaultValues
{
public bool SetName(int i, string value)
{
switch (i)
{
case 0:
{
Name.Properties.Settings.Default.ChName1 = value;
break;
}
case 1:
{
Name.Properties.Settings.Default.ChName2 = value;
break;
}
default:
return false;
}
Name.Properties.Settings.Default.Save();
return true;
}
public string GetName(int i)
{
switch (i)
{
case 0:
return Name.Properties.Settings.Default.ChName1;
case 1:
return Name.Properties.Settings.Default.ChName2;
default:
return "Not Implemented";
}
}
}
This would be called like this
GetDefaultValues Vlues = new GetDefaultValues();
bool success = Vlues.SetName(0, "SomeName");
string SomeString = Vlues.Name(1);
You can make the SetName method a void method if you don't want to have the info if it worked or not.
I'm trying to edit an enum value in a class instance based on whether that instance appears in a dictionary of type <string, myClass>. What seems logical to me is to do the code snippets below:
if (pumpDict.ContainsKey(ID))
{
foreach(KeyValuePair<string, PumpItem> kvp in pumpDict)
{
if(kvp.Key == ID)
{
kvp.Value.state = kvp.Value.state.Available; //error here
kvp.Value.fuelPumped = fuelPumped;
kvp.Value.fuelCost = fuelCost;
break;
}
}
}
else
{
PumpItem pump = new PumpItem();
pumpDict.Add(ID, pump);
}
And my PumpItems class is such:
namespace PoSClientWPF
{
public enum pumpState
{
Available,
customerWaiting,
Pumping,
customerPaying
};
public enum fuelSelection
{
Petrol,
Diesel,
LPG,
Hydrogen,
None
};
class PumpItem
{
public double fuelPumped;
public double fuelCost;
public fuelSelection selection;
public pumpState state;
public PumpItem()//intialize constructor
{
this.fuelPumped = 0;
this.fuelCost = 0;
this.selection = fuelSelection.None;
this.state = pumpState.Available;
}
}
}
I was led to believe that to have an enum value in a constructor, they have to be set up as above, with a new instance of those enums declared in the class body.
It seems to me, that what I'm trying to do is logical but I am getting an error on the right hand side of the assignation which states:
"member PoSClientWPF.pumpState.Available cannot be accessed with an instance reference; qualify is with a type name instead"
I've searched for this error among several forums but only seem to find errors involving calling static variables incorrectly. Can anyone point me in the direction of a solution?
Thanks in advance.
You are incorrectly accessing the Enum member:
// this is incorrect
kvp.Value.state = kvp.Value.state.Available; //error here
// this is the correct way
kvp.Value.state = PoSClientWPF.pumpState.Available;
You know you have a dictionary?
PumpItem pumpItem = pumpDict[ID];
pumpItem.state = PoSClientWPF.pumpState.Available;
or
PumpItem pumpItem;
if (pumpDict.TryGetValue(ID, out pumpItem))
{
pumpItem.state = PoSClientWPF.pumpState.Available;
}
else
{
pumpItem = new PumpItem();
pumpDict.Add(ID, pumpItem);
}
Could just add ID to PumpItem and use a List
PumpItem pumpItem = pumpList.FirstOrDefualt(x => x.ID == ID)
if (pumpItem == null)
pumpList.Add(new PumpItem(ID));
else
pumpItem.state = PoSClientWPF.pumpState.Available;
class PumpItem
{
public double fuelPumped = 0;
public double fuelCost = 0;
public fuelSelection selection = fuelSelection.None;
public pumpState state = pumpState.Available;
public Int32? ID = null;
public PumpItem()//intialize constructor
{ }
public PumpItem(Int32? ID)
{
this.ID = ID;
}
}
I was looking for a similar way to create an alias for something else like its possible in C using preprocessor (this question is a bit similar, couldn't find anything useful there).
This is the problem: I've got a method that receives an array, but each position of the array has a specific meaning, like they where different parameters with specific names. What I want to do is to make my code easier to read (and write) by using those specific names, but, on the other hand, I don't want to create another method call (like in example 1) nor assign the array positions to new variables (example 2), because the performance is critical.
Example 1:
void OriginalMethodSignature(Type[] values)
{
SimplifiedMethod(values[0], values[1], ... values[n]);
}
void SimplifiedMethod(Type specificName1, Type specificName2, ... Type specificNameN)
{
// simple implementation using specific names instead of values[n]
}
Example 2:
void OriginalMethodSignature(Type[] values)
{
Type specificName1 = values[0];
Type specificName2 = values[1];
...
Type specificNameN = values[n];
// simple implementation using specific names instead of values[n]
}
I cannot change the method signature because its used in a dellegate, the Type is fixed.
The next example is a bit better, but still not optimum:
void OriginalMethodSignature(Type[] values)
{
// implementation using values[specificName1] ... values [specificNameN]
}
const int specificName1 = 0;
const int specificName2 = 1;
...
const int specificNameN = n-1;
Is there any way to create an snippet for this purpose? If yes, how would it be?
There isn't any built in way to do what you wan't, because you shouldn't really be doing it at all. You should be using an object with properties instead of an array.
Anyway, you can make an object that encapsulates the array, so that the properties use the array as storage:
public class NamedObject {
private Type[] _values;
public NamedObject(Type[] values) {
_values = values;
}
public SpecificName1 { get { return _values[0]; } set { _values[0] = value; } }
public SpecificName2 { get { return _values[1]; } set { _values[1] = value; } }
public SpecificName3 { get { return _values[2]; } set { _values[2] = value; } }
public SpecificName4 { get { return _values[3]; } set { _values[3] = value; } }
public SpecificName5 { get { return _values[4]; } set { _values[4] = value; } }
public SpecificName6 { get { return _values[5]; } set { _values[5] = value; } }
}
Now you can use the object to access the array:
void OriginalMethodSignature(Type[] values) {
NamedObject obj = new NamedObject(values);
// get a value
Type x = obj.SpecificName4;
// set a value
obj.SpecificName2 = x;
}
Create a dedicated class or struct, and parse the array into it.
public class MyClassOfStuff
{
Type SpecificName1 {get;set;}
Type SpecificName2 {get;set;}
public static MyClassOfStuff Parse(Type[] value)
{
Type specificName1 = values[0];
Type specificName2 = values[1];
...
Type specificNameN = values[n];
}
}
void OriginalMethodSignature(Type[] values)
{
var mystuff = MyClassOfStuff.Parse(values);
}
This is my custom textBox:
public class TextBoxInputNumbers : TextBox
{
Regex regex;
public enum DatatypesInput
{
Integer, Decimals
}
public TextBoxInputNumbers()
{
DatatypeInput = DatatypesInput.Integer;
}
public DatatypesInput DatatypeInput
{
set
{
switch (value)
{
case DatatypesInput.Integer:
regex = new Regex("[^0-9.-]+");
break;
case DatatypesInput.Decimals:
regex = new Regex("[^0-9-]+");
break;
}
}
}
protected override void OnPreviewTextInput(System.Windows.Input.TextCompositionEventArgs e)
{
e.Handled = regex.IsMatch(e.Text);
}
}
And I'd like to show the property DatatypeInput in XAML, but they cannot recognize any element of my enum.
You can convert the enun name to a string using the Enum.GetName() method:
get
{
return Enum.GetName(typeof(DatatypesInput), value);
}
and then bind to that value in your XAML.
Is that what you are looking for? Use Enum.GetNames() is you need the list of all valid names.