I'm learning C# and Unity3D for a few months and now I stumbled on a logic, which hopefully somebody can describe to me.
(I already googled for hours and even looked up if other languages use enums that way.)
This code is from a free asset from the unity asset store, which I try to anatomize.
Everything is fine and understandable for me, but then it comes to the functions GetSliderData() and SetSliderData().
My Question: How does the modulo part works?
Why dividing anyway, when it comes to getting and setting values? Or is it some kind of syntax, like the lambda expression "=>" which is not ">="(less or equal sign)
Thank you in advance for your time!
Dom
public class SliderData : ScriptableObject
{
// Data storage
public List<float> sliderData;
/* Use a single enum as retrieval label for any slider by using a splitter
* value as interval. */
private const int ENUM_INTERVAL = 16;
public enum SliderField
{
// Customizer sliders
DEPTH_MIN,
DEPTH_MAX,
PERLIN_SPEED,
PERLIN_LEVEL,
ZONE_PERLIN_SPEED,
ZONE_PERLIN_LEVEL,
MAP_PERLIN_SPEED,
MAP_PERLIN_LEVEL,
}
/// Retrieves the value of the slider belonging to the given field constant.
public float GetSliderData(SliderField field)
{
return sliderData[(int)field % ENUM_INTERVAL];
}
/// Sets the value of the slider belonging to the given field constant.
public void SetSliderData(SliderField field, float value)
{
sliderData[(int)field % ENUM_INTERVAL] = value;
}
}
The % seems to have the purpose of wrap-around the given field value onto the existing indices of the sliderData list.
If the value reaches/exceeds the ENUM_INTERVAL it will instead start over from 0.
For your methods indeed this seems a bit redundant if using the enum values since there are only 8 of them anyway. But it could be triggered via type casting e.g. (SliderField)17 .. but why would someone do that?
Anyway this seems to simply assume that the sliderData list contains at least 16 elements ...
In general to be honest I wouldn't use such a structure but rather store and access the values via actual fields instead of this kind of "dictionary" List.
Ofcourse depends on the use-case and how exactly your asset is used later. It seems there is some behavior involved you didn't share here.
But instead of going through the magic enum and list indices - why not simply have
public class SliderData : ScriptableObject
{
public float DEPTH_MIN;
public float DEPTH_MAX;
public float PERLIN_SPEED;
public float PERLIN_LEVEL;
public float ZONE_PERLIN_SPEED;
public float ZONE_PERLIN_LEVEL;
public float MAP_PERLIN_SPEED;
public float MAP_PERLIN_LEVEL;
}
Related
I want to Show the field in UnityInspector based on specific enum field.
Lets say this is the enum class
public enum Mode
{
None,
Movement,
Rotation,
Scale
}
I want to enable this field if "Movement or Scale" is selected from the enum dropdown, otherwise hide the field.
public Vector3 NewValues;
With Odin I can do:
[ShowIf("tweenMode", TweenMode.Movement)]
public Vector3 NewValues;
But that will work only on Movement enum. Any idea on how to make it work on multiple enums? Thanks
Afaik you can simply do something like
private bool showNewValues => tweenMode == TweenMode.Movement || tweenMode == TweenMode.Rotation;
[ShowIf(nameof(showNewValues))]
public Vector3 NewValues;
See ShowIf
You can use a property like mentioned before. You can also make use of Odin's attribute expressions which where added in version 2.1.0.0
[ShowIf("#tweenMode == TweenMode.Movement || tweenMode == TweenMode.Rotation")]
public Vector3 NewValues;
If you consider that easier / more readable is up to you, but it's another option.
I have a struct for a game I am building that looks like this:
using System;
public readonly struct Target
{
public Target((int Min, int Max) range, string[] targetTypes)
{
Range = range;
TargetType = ParseTypes(targetTypes);
}
public (int Min, int Max) Range { get; }
public TargetTypes TargetType { get; }
[Flags]
public enum TargetTypes { None = 0, Self = 1, Enemy = 2, Player = 4, Character = 8, Area = 16 }
}
I would like to take all of the values in the string array and cast them into a single enum (not an array of enum values, which I believe is what is happening in the answer to this question).
The thing is a Target can have multiple types. I figured an enum was the best way to represent this, and also figured defining the enum inside the struct wasn't a terrible idea, but this could be an anti-pattern (coming from a JS background, be gentle!).
I like this whole enumeration types as bit flags thing, hence the numbering, that's what sent me down this path.
Yes, I control the inputs, so happy to hear why/how I should do this differently - thanks for your time!
You could use the following.
TargetType = (TargetTypes)Enum.Parse(typeof(TargetTypes),string.Join(",",targetTypes));
The second parameter of Enum.Parse accepts either a single value/constant representing the enum or a list of named constants or underlying values delimited by commas (,).
Thank you #asawyer for pointing the way. I missed an important part of the documentation (always RFTM twice!):
Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object.
There's no need for anything fancy here, Parse does the trick:
TargetType = (TargetTypes) Enum.Parse(typeof(TargetTypes), string.Join(",", targetTypes));
I have an enum like so.
public enum TimeFrame
{
Morning = 1,
Afternoon,
Evening
}
When an object containing a property of type TimeFrame is stored, there's a conversion using a switch statement making each value explicitly to 1, 2, and 3. The command string created is substituted from e.g. Evening to 3. The same when fetching from the DB - if there's a value of 1, it's being mapped manually and explicitly into Morning.
Is there a smooth way to storage the values of the enum "as is"? Or should we avoid doing so for a reason?
I've tried straight-off approach but that only gives the fall-back value all the way...
TimeFrame = row["TimeFrame"] as TimeFrame? ?? TimeFrame.Morning
You can cast enums to ints and vice versa, this is very fast. You can also convert between enums and strings, takes a bit more code, time, and storage. You can then trivially store ints or strings in your database.
If for some reason the O/R-mapper (or whatever technology you are using) cannot handle enum values, you can create an int property translating your enum:
// Do not map!
public TimeFrame TimeFrame { get; set; }
// Map!
public int TimeFrameInt {
get { return (int)TimeFrame; }
set { TimeFrame = (TimeFrame)value; }
}
The translation between ints and enums is simply done with casts; no switch statements required. This is possible and very fast, since enums are represented by ints under the hood.
I have a set of codes that are particular to the application (one to one mapping of the code to its name), and I've been using enums in C# to represent them. I'm not sure now if that is even necessary. The values never change, and they are always going to be associated with those labels:
Workflow_Status_Complete = 1
Workflow_Status_Stalled = 2
Workflow_Status_Progress = 3
Workflow_Status_Complete = 4
Workflow_Status_Fail = 5
Should I use an enum or a class with static members?
Static members of type int seems to be inferior to an enum to me. You lose the typesafety of an enum. And when debugging you don't see the symbolic name but just a number.
On the other hand if an entry consists of more than just a name/integervalue pair a class can be a good idea. But then the fields should be of that class and not int. Something like:
class MyFakeEnum
{
public static readonly MyFakeEnum Value1=new MyFakeEnum(...);
}
Use an enum. Even though your codes never change, it will be difficult to know what the value represents just by inspection. One of the many strengths of using enums.
enum RealEnum : uint
{
SomeValue = 0xDEADBEEF,
}
static class FakeEnum
{
public const uint SomeValue = 0xDEADBEEF;
}
var x = RealEnum.SomeValue;
var y = FakeEnum.SomeValue;
// what's the value?
var xstr = x.ToString(); // SomeValue
var ystr = y.ToString(); // 3735928559
Not even the debugger will help you much here, especially if there are many different values.
Check out the State Pattern as this is a better design. With the idea you are using you'll end up with a large switch/if-else statement which can be very difficult to keep up.
I would lean towards enums as they provide more information and they make your codes "easier to use correctly and difficult to use incorrectly". (I think the quote is from The Pragmatic Programmer.
My application deals with percentages a lot. These are generally stored in the database in their written form rather than decimal form (50% would be stored as 50 rather than 0.5). There is also the requirement that percentages are formatted consistently throughout the application.
To this end i have been considering creating a struct called percentage that encapsulates this behaviour. I guess its signature would look something like this:
public struct Percentage
{
public static Percentage FromWrittenValue();
public static Percentage FromDecimalValue();
public decimal WrittenValue { get; set; }
public decimal DecimalValue { get; set; }
}
Is this a reasonable thing to do? It would certianly encapsulate some logic that is repeated many times but it is straightforward logic that peopel are likely to understand. I guess i need to make this type behave like a normal number as much as possible however i am wary of creating implicit conversions to a from decimal in case these confuse people further.
Any suggestions of how to implement this class? or compelling reasons not to.
I am actually a little bit flabbergasted at the cavalier attitude toward data quality here.
Unfortunately, the colloquial term "percentage" can mean one of two different things: a probability and a variance. The OP doesn't specify which, but since variance is usually calculated, I'm guessing he may mean percentage as a probability or fraction (such as a discount).
The extremely good reason for writing a Percentage class for this purpose has nothing to do with presentation, but with making sure that you prevent those silly silly users from doing things like entering invalid values like -5 and 250.
I'm thinking really more about a Probability class: a numeric type whose valid range is strictly [0,1]. You can encapsulate that rule in ONE place, rather than writing code like this in 37 places:
public double VeryImportantLibraryMethodNumber37(double consumerProvidedGarbage)
{
if (consumerProvidedGarbage < 0 || consumerProvidedGarbage > 1)
throw new ArgumentOutOfRangeException("Here we go again.");
return someOtherNumber * consumerProvidedGarbage;
}
instead you have this nice implementation. No, it's not fantastically obvious improvement, but remember, you're doing that value-checking in each time you're using this value.
public double VeryImportantLibraryMethodNumber37(Percentage guaranteedCleanData)
{
return someOtherNumber * guaranteedCleanData.Value;
}
Percentage class should not be concerned with formatting itself for the UI. Rather, implement IFormatProvider and ICustomFormatter to handle formatting logic.
As for conversion, I'd go with standard TypeConverter route, which would allow .NET to handle this class correctly, plus a separate PercentageParser utility class, which would delegate calls to TypeDescriptor to be more usable in external code. In addition, you can provide implicit or explicit conversion operator, if this is required.
And when it comes to Percentage, I don't see any compelling reason to wrap simple decimal into a separate struct other than for semantic expressiveness.
It seems like a reasonable thing to do, but I'd reconsider your interface to make it more like other CLR primitive types, e.g. something like.
// all error checking omitted here; you would want range checks etc.
public struct Percentage
{
public Percentage(decimal value) : this()
{
this.Value = value
}
public decimal Value { get; private set; }
public static explicit operator Percentage(decimal d)
{
return new Percentage(d);
}
public static implicit operator decimal(Percentage p)
{
return this.Value;
}
public static Percentage Parse(string value)
{
return new Percentage(decimal.Parse(value));
}
public override string ToString()
{
return string.Format("{0}%", this.Value);
}
}
You'd definitely also want to implement IComparable<T> and IEquatable<T> as well as all the corresponding operators and overrides of Equals, GetHashCode, etc. You'd also probably also want to consider implementing the IConvertible and IFormattable interfaces.
This is a lot of work. The struct is likely to be somewhere in the region of 1000 lines and take a couple of days to do (I know this because it's a similar task to a Money struct I wrote a few months back). If this is of cost-benefit to you, then go for it.
This question reminds me of the Money class Patterns of Enterprise Application Architecture talks about- the link might give you food for thought.
Even in 2022, .Net 6 I found myself using something just like this. I concur with Michael on his answer for the OP and like to extend it for future Googlers.
Creating a value type would be indispensable in explaining the domain's intent with enforced immutability. Notice especially in the Fraction Record you will get a Quotient that would normally cause an exception however here we can safely show d / 0 with no error, likewise all other inherited children are also granted that protection (It also offers an excellent place to establish simple routines to check validity, data rehydration (as if DBA's don't make mistakes), serialization concerns just to name a few.)
namespace StackOverflowing;
// Honor the simple fraction
public record class Fraction(decimal Dividend, decimal Divisor)
{
public decimal Quotient => (Divisor > 0.0M) ? Dividend / Divisor : 0.0M;
// Display dividend / divisor as the string, not the quotient
public override string ToString()
{
return $"{Dividend} / {Divisor}";
}
};
// Honor the decimal based interpretation of the simple fraction
public record class DecimalFraction(decimal Dividend, decimal Divisor) : Fraction(Dividend, Divisor)
{
// Change the display of this type to the decimal form
public override string ToString()
{
return Quotient.ToString();
}
};
// Honor the decimal fraction as the basis value but offer a converted value as a percentage
public record class Percent(decimal Value) : DecimalFraction(Value, 100.00M)
{
// Display the quotient as it represents the simple fraction in a base 10 format aka radix 10
public override string ToString()
{
return Quotient.ToString("p");
}
};
// Example of a domain value object consumed by an entity or aggregate in finance
public record class PercentagePoint(Percent Left, Percent Right)
{
public Percent Points => new(Left.Value - Right.Value);
public override string ToString()
{
return $"{Points.Dividend} points";
}
}
[TestMethod]
public void PercentScratchPad()
{
var approximatedPiFraction = new Fraction(22, 7);
var approximatedPiDecimal = new DecimalFraction(22, 7);
var percent2 = new Percent(2);
var percent212 = new Percent(212);
var points = new PercentagePoint(new Percent(50), new Percent(40));
TestContext.WriteLine($"Approximated Pi Fraction: {approximatedPiFraction}");
TestContext.WriteLine($"Approximated Pi Decimal: {approximatedPiDecimal}");
TestContext.WriteLine($"2 Percent: {percent2}");
TestContext.WriteLine($"212 Percent: {percent212}");
TestContext.WriteLine($"Percentage Points: {points}");
TestContext.WriteLine($"Percentage Points as percentage: {points.Points}");
}
PercentScratchPad
Standard Output:
TestContext Messages:
Approximated Pi Fraction: 22 / 7
Approximated Pi Decimal: 3.1428571428571428571428571429
2 Percent: 2.00%
212 Percent: 212.00%
Percentage Points: 10 points
Percentage Points as percentage: 10.00%
I strongly recommend you just stick with using the double type here (I don't see any use for the decimal type either, as wouldn't actually seem to require base-10 precision in the low decimal places). By creating a Percentage type here, you're really performing unnecessary encapsulation and just making it harder to work with the values in code. If you use a double, which is customary for storying percentages (among many other tasks), you'll find dealing with the BCL and other code a lot nicer in most cases.
The only extra functionality that I can see you need for percentages is the ability to convert to/from a percentage string easily. This can be done very simply anyway using single lines of code, or even extension methods if you want to abstract it slightly.
Converting to percentage string :
public static string ToPercentageString(this double value)
{
return value.ToString("#0.0%"); // e.g. 76.2%
}
Converting from percentage string :
public static double FromPercentageString(this string value)
{
return double.Parse(value.SubString(0, value.Length - 1)) / 100;
}
I think you may be mixing up presentation and logic here. I would convert the percentage to a decimal or float fraction (0.5) when getting it from the database and then let the presentation deal with the formatting.
I'd not create a separate class for that - this just creates more overhead. I thinkg it will be faster just to use double variables set to the database value.
If it is common knowledge that the database stores percentages as 50 instead of 0.5, everybody will understand statemens like part = (percentage / 100.0) * (double)value.