0

pretext:

ChestType is an enum

public enum ChestType
{
    COMMON,
    GEMNGOLDCHEST,
    GODLYCHEST,
    ASSCHEST
}

slotAndChestIndex is a ChestType?[]

chestSlotsAndChestsSaved is an int[]

(Sorry for the bad names)

            slotAndChestIndex[i] = (ChestType?)chestSlotsAndChestSaved[i] ?? null;

I believe the above line says: "If I cant cast this int to a ChestType? then express it as null"

ChestType? is however being set to a value of -1 which seems weird to me.

Am I doing something wrong here? Event when I try set it to default(ChestType?) it still sets it to -1 lol. I thought the default of any Nullable type is null.

Please tell me what I'm not understanding!

Sebastian King
  • 341
  • 1
  • 11
  • "ChestType is an enum" -- can you post the enum? – Chaim Eliyah Mar 15 '18 at 23:16
  • 1
    An enum can have a values that are not limited to one of its named members (see chapter "9.3.10 Enumeration types" of the [current C# spec](http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf)). Hence why the cast of an int to your enum type never fails. Since you want to check whether an int value matches a given enum member, you should do something like shown at the link provided in Chaim Eliyah's comment... –  Mar 15 '18 at 23:20
  • To be fair, for ints, it does say you can `EnumName thing = (EnumName)yourInt;`; I've never tried to use a nullable enum... – Chaim Eliyah Mar 15 '18 at 23:22
  • 4
    `?? null` is pointless. It means `if a value is null, return null` - which it does without that code already. – mjwills Mar 15 '18 at 23:22
  • Okay, seeing your edit; if the value of `intArray[i]` is not in 0, 1, 2, 3, you will get `null`. Like I said, I don't know about nullable enums (possible anti-pattern, imho) so it's quite possible that `null` somehow equates to -1. – Chaim Eliyah Mar 15 '18 at 23:29
  • 1
    @ChaimEliyah yeah i was thinking it's possibly a bad design, but it solves a little problem nicely. Can't see it killing my program yet... Thanks for your answer tho! – Sebastian King Mar 15 '18 at 23:48

2 Answers2

4

You can't validate if it is defined within your enum that way; it'll just assign the value of your variable chestSlotsAndChestSaved[i] in it (even though it's -1 and it's not defined in your enum).

The way you can verify this is with:

slotAndChestIndex[i] = (ChestType?)(Enum.IsDefined(typeof(ChestType), chestSlotsAndChestSaved[i]) ? chestSlotsAndChestSaved[i] : (int?)null);

PS: I haven't tested the code, even though, Enum.IsDefined(typeof(ChestType), chestSlotsAndChestSaved[i]) is your way to go.

IFebles
  • 328
  • 1
  • 2
  • 12
2

Neither the ?? operator nor the cast you're doing do quite what you think.

To start with, the cast you've used will never produce a null value - casting from an int to (most) enums will simply produce a value of the type of the enum, but potentially with a numeric value, not one of the enum members. The fact that you cast to ChestType? rather than ChestType doesn't change that. In addition, if a direct cast is performed like you've shown and can't be performed an exception will be raised, and the result will not be null. This should never happen for literal conversions like this, but could happen when casing between classes.

Next, the ?? operator, also known as the null-coalescing operator, evaluates to the left operand if the left operand is not null, and evaluates to the right operand if the left operand is null. So if chestSlotsAndChestSaved[i] was equal to null, the expression would become the right hand operand - however since the right operand is always null, that part of the expression effectively does nothing.

Overall, the most likely reason that slotAndChestIndex[i] is coming back as -1 is because chestSlotsAndChestSaved[i] is -1.

Logan Hunter
  • 397
  • 4
  • 8
  • Oh man, thank you for the detailed answer. I'll have to read it over to get a better understanding. I think I confused the ?? with ? operator that's expressed in the ternary operation... Cheers! – Sebastian King Mar 15 '18 at 23:45
  • The `??` operator works as "if the first value is not null, then use it; if not, use the one in the right instead". Cheers! – IFebles Mar 15 '18 at 23:52