I'm working on a game with Unity in which the player has some spells. I have an enum that contains all of these and I want to attach them a bool value. I think I can use a System.Collections.Generics.Dictionary with the Spells as Keys and the Boolean as Value, but is there a simpler way to do such a thing?
You can simplify Dictionary<Spell, bool> hasSpell into HashSet<Spell> (you want only Key, not Value from the initial Dictionary):
public enum Spell {
Fireball,
Levitate,
Resurrect,
};
...
HashSet<Spell> abilities = new HashSet<Spell>() {
Spell.Fireball,
Fireball.Levitate,
};
...
// If the hero can resurrect...
if (abilities.Contains(Spell.Resurrect)) {
// ...let him raises from the dead
}
Individually the simplest way of pairing two data values is to use a value tuple. This feature can be used on any Unity version from 2018.3 onwards as that's when it stopped using outdated C# versions.
var spell = ("Fireball", true);
If you'd rather be more explicit about types:
(string, bool) spell = ("Fireball", true);
(This is another approach in making things "easy")
Yes, dictionnary are simple collections but it's not really what I expect. I want something just to say "this value from the enum is true, this one is false"
This sounds you need a nice class that encapsulates the less-simple or more low-level structure (e.g. dictionary or hashset). This will things easy from the outside / API-isde.
For example:
public enum Spell
{
Firebolt,
Rage,
Flash,
};
public class SpellState
{
private HashSet<Spell> _enabled = new HashSet<Spell>();
public void EnableSpell(Spell spell)
{
_enabled.Add(spell);
}
public void DisableSpell(Spell spell)
{
_enabled.Remove(spell);
}
public bool IsSpellEnabled(Spell spell)
{
return _enabled.Contains(spell);
}
}
Usage
var spellState = new SpellState();
spellState.EnableSpell(Spell.Rage);
// later
if (spellState.IsSpellEnabled(Spell.Flash))
{
spellState.DisableSpell(Spell.Rage);
// todo
}
You could use a single bitwise value by defining enum flags, so long as you have a limited number of spells.
[Flags]
public enum Spell : long
{
Firebolt = (1 << 0),
Rage = (1 << 1),
Flash = (1 << 2),
};
Related
I want to add a duck-typed struct to an dictionary but i get the following error:
Argument 2: cannot convert from '[] options>' to 'UnityEngine.Object'
This is the code i have:
public class Dynamic_Interface
{
private static Dictionary<int, Object> Interface_steps = new Dictionary<int, Object>();
Dynamic_Interface()
{
var sentences = new[]
{
new
{
identifier = 1,
text = "string explain",
options = new[]
{
new
{
next = 2,
value = "this is the first option"
},
new
{
next = 2,
value = "this is the second option"
},
new
{
next = 2,
value = "this is the third option"
},
new
{
next = 2,
value = "this is the fourth option"
},
}
},
new
{
identifier = 2,
text = "string explain second var",
options = new[]
{
new
{
next = 3,
value = "this is the second first option"
},
new
{
next = 3,
value = "this is the second second option"
},
new
{
next = 3,
value = "this is the second third option"
},
new
{
next = 3,
value = "this is the second fourth option"
}
}
},
};
foreach (var sentence_obj in sentences)
{
Interface_steps.Add(sentence_obj.identifier, sentence_obj);
}
}
}
So in the end i want a dictionary containing each object in the sentences[] that has the the identifier key as name in the dictionary.
I am used to to javascript and this is really my first time doing c# so sorry for the beginner mistake. But i really cant seem to find how to get this to work.
If something is unclear let me know so i can clarify..
So, what is happening here?
When we take a closer look at the error message
Argument 2: cannot convert from '[] options>' to 'UnityEngine.Object'
it tells us that we are trying to convert the options array to the type UnityEngine.Object. Hmmm. this is weird we didn't define our Dictionary with this Unity nonsense, so why is it using that instead of C#'s Object class?!
Well you are propably using other Unity classes an probably have something like
using UnityEngine;
in your namespace. The problem with C# is that it's Object class also resides in a namespace which is called System, making it only fully identifieable by using System.Object. So if you don't have
using System;
it will happily try to use UnityEngine.Object instead of System.Object when you type Object. Thus this weird compiler error will occur.
So just use System.Object and everything is fine right?
Well Yes. But there is more to the Story!
C# also has defined aliases for it's most common types - the so called built-in types:
bool System.Boolean
byte System.Byte
sbyte System.SByte
char System.Char
decimal System.Decimal
double System.Double
float System.Single
int System.Int32
uint System.UInt32
long System.Int64
ulong System.UInt64
object System.Object
short System.Int16
ushort System.UInt16
string System.String
You will find that lowercase object is just an alias to System.Object. But wait! Doesn't that make object always use System.Object regardless of our using statements? The answer is yes, yes it does...
Let me illustrate by following example how tricky namespacing in C# can actually be:
public class Object
{
public string Name { get; set; }
}
public class TestConsole
{
public static void Main(string[] args)
{
Object fakeObject = new Object(); // -> Custom Object class
object realDeal = new object(); // -> System.Object
string name = fakeObject.Name // OK
name = realDeal.Name // NOT OK
}
}
So does that mean that we should always use the built-in alias when using System classes? Not really but we should rather use the naming convention that is used by Microsoft. That means whenever you use the class like a datatype you should use the built-in and whenever you use static members of the class you should use it's full name. For example:
object humberto = "humberto";
string rudolf = "rudolf";
Object.Equals(humberto, rudolf);
Strong typing is one of advantages of C#, its a bit more verbose than ducktyping but saves you a lot of headache, if possible try to restrain from var, its a few characters shorter but if you use strong types its much harder to accidentally ask the compiler to do something different than what you actually want:
Two options for alternative approaches that seem to immediately stand out are
class myClass { int next; string value; };
Dictionary <int, myClass> dict;
or, possibly, although I think this is not quite what you are trying to do
Dictionary<int, Dictionary<int,string>> dict;
Second option doesn't require you to declare a class type, but remember that dictionaries require unique keys. It kind of reads that you want to use array index as a key, but then you still use a dictionary, is there a reason for that? My solutions might be a bit off, but I'd be happy to suggest more if you could explain what kind of lookup you want to make.
Maybe you want to combine the above into
Dictionary<int, Dictionary<int,myClass>> dict;
I'm struggling a bit to understand the iteration piece here of how I would check if if the entity variable below has all of the Enum.Component entries in the variable comps. I can achieve this relatively straight-forwardly if I know there will be only one Component via a .ForEach and a basic comparison (e.g. entity.ForEach(comp => Console.WriteLine(comp.COMPONENT == Enum.Component.EXPERIENCE));), but not if I need to check for multiple components.
I'm trying to understand the nuances of C# a bit better, so I don't want to brute force this with an actual foreach (in the conventional foreach(var x in exes) type of way) or something similar, but really want to understand how I would implement this via these objects through these IEnumerable functions and working with lambda expressions. As such, I need an answer utilizing these things, unless of course this is not technically possible, though probably it is, I'm guessing.
// The Component.IComponent Interface (it's in the Component namespace)
interface IComponent {
Enum.Component COMPONENT {
get;
}
}
// The Enum.Component (it's in the Enum namespace)
enum Component {
EXPERIENCE,
HEALTH
}
// The Component.Experience (it's in the Component namespace)
class Experience : IComponent {
public ThresholdValue xp;
public int level;
public Enum.Component COMPONENT {
get {
return Enum.Component.EXPERIENCE;
}
}
}
// It probably doesn't matter, but ENTITY_MANAGER is this type
Dictionary<Guid, List<Component.IComponent>>
// Trial code beings here:
Guid GUID = new Guid();
ENTITY_MANAGER.getEntities().Add(GUID, new List<Component.IComponent> { new Component.Experience(50, 3), new Component.Health(20, 25) });
List<Component.IComponent> entity = ENTITY_MANAGER.getEntities()[new Guid()];
Enum.Component[] comps = new Enum.Component[] {
Enum.Component.EXPERIENCE,
Enum.Component.HEALTH
};
// This is where I don't know what to do and know this is wrong
comps.All(v => entity.ForEach(comp => Console.WriteLine(comp.COMPONENT == v)));
You can easily do this via Flags!
https://msdn.microsoft.com/en-us/library/system.flagsattribute(v=vs.110).aspx
First do this with your Enum:
[Flags]
enum Component {
None = 0,
EXPERIENCE = 1 << 0,
HEALTH = 1 << 1,
All = (1 << 2) - 1
}
This basically will store your values as powers of 2, with 'All' being the sum of all your flags, in this case Exp and Hp are 1 and 2, so All is 3 (1+2)
Now you can just do this in your entity class:
public Enum.Component Flags => comps.Select(c => c.Component).Distinct().Sum();
public bool HasAllFlags => Flags == Enum.Component.All;
We make our enum all distinct base 2, with all the next step -1, which means All is the sum of all your enum listings.
Then we just sum up the Enums (We might have to convert to an int first then back to the enum, I don't remember if you can just add Enums together in C#) and check if they == Component.All.
There you go!
Issue:
enum's referenced by gameobject scripts via inspector variables become out of order when the enum has new entries added before the referenced index.
Details:
So I have multiple systems such as item lists, localisation strings, etc which are dynamically built by parsing external files. This parsing creates enum's which are used to reference the items by gameobject's via script inspector variables. Here's the parsed output by my localisation system as an example:
public enum LocaleID
{
LocalisedStrings_ENGB,
LocalisedStrings_ENUS,
//...
MAX,
}
public enum StringID
{
String_EMPTY,
String_Inventory,
String_Recipes,
String_Tools,
String_Journal,
//...
}
public static class LocalisedStrings
{
private static string[] SCLocalisedStrings_ENGB =
{
"",
"Inventory",
"Recipes",
"Tools",
"Journal",
//...
}
private static LocaleID currentLocale = (LocaleID)0;
private static string[] activeSC = SCLocalisedStrings_ENGB;
public static void SetLocale(LocaleID newLocale)
{
currentLocale = newLocale;
switch(newLocale)
{
case LocaleID.LocalisedStrings_ENGB:
activeSC = SCLocalisedStrings_ENGB;
break;
case LocaleID.LocalisedStrings_ENUS:
activeSC = SCLocalisedStrings_ENUS;
break;
}
}
//entry interface:
public static string Get(StringID stringID)
{
return activeSC[(int)stringID];
}
}
This simply returns the string via the enum index based off the set locale.
So I'd have something such as a name of an NPC exposed on a character as:
[SerializeField]
public StringID SpeakerTitle;
and set that through the inspector.
The issue is a rather obvious and expected one - if the enum is parsed differently, for example an extra entry is added to the top (for example for sorting purposes) or removed (for cleaning up obsolete entries), then all referenced enum's will become out of order by 1 spot since they'll be referencing the index of the enum entry.
A simple solution would be to impose a rule of only adding to the end and never removing entries that become stale. This becomes quite wasteful, so is obviously not very preferable.
What are suggested solutions to this issue? Any examples of how others approach this rather common situation? My preference would of course be something which could be sorted and new entries added anywhere, but we can't have everything we want :)
Just specify explicit numeric values for the entries:
public enum StringID
{
String_EMPTY = 0,
String_Inventory = 1,
String_Recipes = 2,
String_Tools = 3,
String_Journal = 4,
//...
}
That way the ordering is entirely irrelevant to the values. Note that you can do this retrospectively, or in a "just in time" way when you need to make what would otherwise be a breaking change.
(I'd personally get rid of the String_ prefix as well, but that's a different matter.)
I would use an explicit map rather than a naked array; for example:
private static Dictionary<StringID,string> SCLocalisedStrings_ENGB =
new Dictionary<StringID,string>
{
{StringID.String_EMPTY, ""},
{StringID.String_Inventory, "Inventory"},
//...
};
and get the value via something like:
string val;
return LocaleStrings.TryGetValue(key, out val) ? val : DefaultStrings[key];
Well... actually, I'd probably have the translations in external files as key/value pairs, but... meh.
Note: you could always put the dictionary data back into an ordered array; but having the explicit map prevents order from mattering.
Assume i have an enumeration:
namespace System.Windows.Forms
{
public enum DialogResult { None, OK, Cancel, Abort, Retry, Ignore, Yes, No }
}
i want to declare a "set" made up of these enumerated types
ShowForm(Form frm, DialogResults allowedResults)
In other languages you would declare:
public DialogResults = set of DialogResult;
And then i can use
ShowForm(frm, DialogResult.OK | DialogResult.Retry);
C# has the notion of Flags, pseudocode:
[Flags]
public enum DialogResults { DialogResult.None, DialogResult.OK, DialogResult.Cancel, DialogResult.Abort, DialogResult.Retry, DialogResult.Ignore, DialogResult.Yes, DialogResult.No }
problem with that it's not real code - Flags does not instruct the compiler to create a set of flags.
in one case the type should only allow one value (DialogResult)
in another case the type should allow multiple values of above (DialogResults)
How can i have a "set" of enumerated types?
Note: i assume it's not possible in C#. If that's the answer: it's okay to say so - the question is answered.
Note: Just because i believe C# language doesn't have the feature doesn't mean it doesn't have the feature - i may just not have found it yet.
Update: another example:
Assume i have an enumeration:
public enum PatronTier
{
Gold = 1,
Platinum = 2,
Diamond = 3,
SevenStar = 7 //Yes, seven
}
i want to declare a "set" made up of these enumerated types
public Tournament
{
public PatronTiers EligibleTiers { get; set; }
}
In other languages you would declare:
public PatronTiers = set of PatronTier;
And then i can use:
tournament.EligibleTiers = PatronTier.Gold | PatronTier.SevenStar;
C# has the notion of Flags, pseudocode:
[Flags]
public enum PatronTiers { PatronTier.Gold, PatronTier.Platinum, PatronTier.Diamond, PatronTier.SevenStar }
problem with that it's not real code.
How can i have a "set" of enumerated types?
Seems like you want an array of things. There are array types in C#, but nothing that is directly equivalent to your examples in terms of compiler support, closest is perhaps DialogResults[], an array of DialogResults.
Try supplying a HashSet of the items you allow. HashSet<T> implements ISet<T>, and it's usually best to work against interfaces than concrete types, especially for method signatures:
ShowForm(Form frm, ISet<DialogResults> allowedResults);
Then you can use Contains to test for items:
if (allowedResults.Contains(DialogResults.OK))
{
}
Somewhat pointless alternative: you could always implement your own Set<Enum> type using Jon Skeet's Unconstrained Melody to give you a nicer syntax from the perspective of the caller and get a little closer to your examples.
I don't suppose you just mean using something like this?
var DialogResults = Enum.GetValues(typeof(DialogResult));
with a .Select(dr => (DialogResult)dr).ToArray() if you want it strongly typed.
I think you want something like this:
foreach (var item in System.Enum.GetValues(typeof(PatronTier)))
{
Console.WriteLine(item);
}
I know this rather goes against the idea of enums, but is it possible to extend enums in C#/Java? I mean "extend" in both the sense of adding new values to an enum, but also in the OO sense of inheriting from an existing enum.
I assume it's not possible in Java, as it only got them fairly recently (Java 5?). C# seems more forgiving of people that want to do crazy things, though, so I thought it might be possible some way. Presumably it could be hacked up via reflection (not that you'd every actually use that method)?
I'm not necessarily interested in implementing any given method, it just provoked my curiosity when it occurred to me :-)
The reason you can't extend Enums is because it would lead to problems with polymorphism.
Say you have an enum MyEnum with values A, B, and C , and extend it with value D as MyExtEnum.
Suppose a method expects a myEnum value somewhere, for instance as a parameter. It should be legal to supply a MyExtEnum value, because it's a subtype, but now what are you going to do when it turns out the value is D?
To eliminate this problem, extending enums is illegal
You're going the wrong way: a subclass of an enum would have fewer entries.
In pseudocode, think:
enum Animal { Mosquito, Dog, Cat };
enum Mammal : Animal { Dog, Cat }; // (not valid C#)
Any method that can accept an Animal should be able to accept a Mammal, but not the other way around. Subclassing is for making something more specific, not more general. That's why "object" is the root of the class hierarchy. Likewise, if enums were inheritable, then a hypothetical root of the enum hierarchy would have every possible symbol.
But no, C#/Java don't allow sub-enums, AFAICT, though it would be really useful at times. It's probably because they chose to implement Enums as ints (like C) instead of interned symbols (like Lisp). (Above, what does (Animal)1 represent, and what does (Mammal)1 represent, and are they the same value?)
You could write your own enum-like class (with a different name) that provided this, though. With C# attributes it might even look kind of nice.
When built-in enums aren't enough, you can do it the old fashion way and craft your own. For example, if you wanted to add an additional property, for example, a description field, you could do it as follows:
public class Action {
public string Name {get; private set;}
public string Description {get; private set;}
private Action(string name, string description) {
Name = name;
Description = description;
}
public static Action DoIt = new Action("Do it", "This does things");
public static Action StopIt = new Action("Stop It", "This stops things");
}
You can then treat it like an enum like so:
public void ProcessAction(Action a) {
Console.WriteLine("Performing action: " + a.Name)
if (a == Action.DoIt) {
// ... and so on
}
}
The trick is to make sure that the constructor is private (or protected if you want to inherit), and that your instances are static.
Enums are supposed to represent the enumeration of all possible values, so extending rather does go against the idea.
However, what you can do in Java (and presumably C++0x) is have an interface instead of a enum class. Then put you standard values in an enum that implements the feature. Obviously you don't get to use java.util.EnumSet and the like. This is the approach taken in "more NIO features", which should be in JDK7.
public interface Result {
String name();
String toString();
}
public enum StandardResults implements Result {
TRUE, FALSE
}
public enum WTFResults implements Result {
FILE_NOT_FOUND
}
You can use .NET reflection to retrieve the labels and values from an existing enum at run-time (Enum.GetNames() and Enum.GetValues() are the two specific methods you would use) and then use code injection to create a new one with those elements plus some new ones. This seems somewhat analagous to "inheriting from an existing enum".
I didn't see anyone else mention this but the ordinal value of an enum is important. For example, with grails when you save an enum to the database it uses the ordinal value. If you could somehow extend an enum, what would be the ordinal values of your extensions? If you extended it in multiple places how could you preserve some kind of order to these ordinals? Chaos/instability in the ordinal values would be a bad thing which is probably another reason why the language designers have not touched this.
Another difficulty if you were the language designer, how can you preserve the functionality of the values() method which is supposed to return all of the enum values. What would you invoke this on and how would it gather up all of the values?
Adding enums is a fairly common thing to do if you go back to the source code and edit, any other way (inheritance or reflection, if either is possible) is likely to come back and hit you when you get an upgrade of the library and they have introduced the same enum name or the same enum value - I have seen plenty of lowlevel code where the integer number matches to the binary encoding, where you would run into problems
Ideally code referencing enums should be written as equals only (or switches), and try to be future proof by not expecting the enum set to be const
If you mean extends in the Base class sense, then in Java... no.
But you can extend an enum value to have properties and methods if that's what you mean.
For example, the following uses a Bracket enum:
class Person {
enum Bracket {
Low(0, 12000),
Middle(12000, 60000),
Upper(60000, 100000);
private final int low;
private final int high;
Brackets(int low, int high) {
this.low = low;
this.high = high;
}
public int getLow() {
return low;
}
public int getHigh() {
return high;
}
public boolean isWithin(int value) {
return value >= low && value <= high;
}
public String toString() {
return "Bracket " + low + " to " + high;
}
}
private Bracket bracket;
private String name;
public Person(String name, Bracket bracket) {
this.bracket = bracket;
this.name = name;
}
public String toString() {
return name + " in " + bracket;
}
}
Saw a post regarding this for Java a while back, check out http://www.javaspecialists.eu/archive/Issue161.html .
I would like to be able to add values to C# enumerations which are combinations of existing values. For example (this is what I want to do):
AnchorStyles is defined as
public enum AnchorStyles {
None = 0,
Top = 1,
Bottom = 2,
Left = 4,
Right = 8,
}
and I would like to add an AnchorStyles.BottomRight = Right + Bottom so instead of saying
my_ctrl.Anchor = AnchorStyles.Right | AnchorStyles.Bottom;
I can just say
my_ctrl.Anchor = AnchorStyles.BottomRight;
This doesn't cause any of the problems that have been mentioned above, so it would be nice if it was possible.
A temporary/local workaround, when you just want very local/one time usage:
enum Animals { Dog, Cat }
enum AnimalsExt { Dog = Animals.Dog, Cat= Animals.Cat, MyOther}
// BUT CAST THEM when using:
var xyz = AnimalsExt.Cat;
MethodThatNeedsAnimal( (Animals)xyz );
See all answers at: Enum "Inheritance"
You can't inherit from/extend an enum, you can use attributes to declare a description. If you're looking for an integer value, that's built-in.
Hmmm - as far as I know, this can't be done - enumerations are written at design-time and are used as a convenience to the programmer.
I'm pretty sure that when the code is compiled, the equivalent values will be substituted for the names in your enumeration, thereby removing the concept of an enumeration and (therefore) the ability to extend it.
Some time back even i wanted to do something like this and found that enum extensions would voilate lot of basic concepts... (Not just polymorphisim)
But still u might need to do if the enum is declared in external library and
Remember you should make a special caution when using this enum extensions...
public enum MyEnum { A = 1, B = 2, C = 4 }
public const MyEnum D = (MyEnum)(8);
public const MyEnum E = (MyEnum)(16);
func1{
MyEnum EnumValue = D;
switch (EnumValue){
case D: break;
case E: break;
case MyEnum.A: break;
case MyEnum.B: break;
}
}
As far as java is concerned it is not allowed because adding elements to an enum would effectively create a super class rather than a sub class.
Consider:
enum Person (JOHN SAM}
enum Student extends Person {HARVEY ROSS}
A general use case of Polymorphism would be
Person person = Student.ROSS; //not legal
which is clearly wrong.