I am pretty close to understand Generics now (I think).
However, just figured that System.Enum is not easy to implement as a generic type. I have this class:
public class Button<TEnum> where TEnum : struct, IConvertible, IComparable, IFormattable {
public TEnum Identifier {
get;
private set; //Set in the ctor
}
}
and
public abstract class AbstractInputDevice<TEnum> where TEnum : struct, IConvertible, IComparable, IFormattable {
private List<Button<TEnum>> _buttons = new List<Button<TEnum>>();
public Button<TEnum> GetButton(TEnum Identifier){
foreach(Button<TEnum> button in _buttons){
if(button.Identifier == Identifier) //<- compiler throws
return button;
}
Debug.Log("'" + GetType().Name + "' cannot return an <b>unregistered</b> '" + typeof(Button<TEnum>).Name + "' that listens to '" + typeof(TEnum).Name + "." + Identifier.ToString() + "'.");
return null;
}
}
An InputDevice might look like that:
public class Keyboard : AbstractInputDevice<KeyCode> {
private void Useless(){
Button<KeyCode> = GetButton(KeyCode.A);
}
}
The compiler throws a compile error right here:
if(button.Identifier == Identifier) //In AbstractInputDevice above
I believe I cannot compare these two TEnums because they are not actually known to be Enums.
And thus no comparison method is available.
I used this resource:
Create Generic method constraining T to an Enum
I appreciate any better solution or fix.
(But I want to keep the Enum entry as a parameter to GetButton(EnumEntry)
)
Instead of the impossible
button.Identifier == Identifier
you should use
EqualityComparer<TEnum>.Default.Equals(button.Identifier, Identifier)
This avoids boxing the value into an object
box (or IComparable
box).
You are trying to perform a reference comparison on a value type (struct), use Equals
for equality instead:
public Button<TEnum> GetButton(TEnum Identifier) {
var button = _buttons
.Where(b => EqualityComparer<TEnum>.Default.Equals(b.Identifier, Identifier))
.FirstOrDefault();
if (button == null)
Debug.Log("'" + GetType().Name + "' cannot return an <b>unregistered</b> '" + typeof(Button<TEnum>).Name + "' that listens to '" + typeof(TEnum).Name + "." + Identifier.ToString() + "'.");
return button;
}
The button.Identifier == Identifier
statement cannot be performed, because the ==
operator does not exist for structs. On a class it would have performed a reference comparison.
And as @JeppeStigNielsen noted in his answer , to prevent a boxing equality comparison, it is better to use the EqualityComparer<TEnum>.Default.Equals
method.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.