我正在编写一些枚举功能,并具有以下功能:
public static T ConvertStringToEnumValue<T>(string valueToConvert, bool isCaseSensitive)
{
if (typeof(T).BaseType.FullName != "System.Enum" && typeof(T).BaseType.FullName != "System.ValueType")
{
throw new ArgumentException("Type must be of Enum and not " + typeof (T).BaseType.FullName);
}
if (String.IsNullOrWhiteSpace(valueToConvert))
return (T)typeof(T).TypeInitializer.Invoke(null);
valueToConvert = valueToConvert.Replace(" ", "");
if (typeof(T).BaseType.FullName == "System.ValueType")
{
return (T)Enum.Parse(Nullable.GetUnderlyingType(typeof(T)), valueToConvert, !isCaseSensitive);
}
return (T)Enum.Parse(typeof(T), valueToConvert, !isCaseSensitive);
}
Run Code Online (Sandbox Code Playgroud)
我称之为:
EnumHelper.ConvertStringToEnumValue<Enums.Animals?>("Cat");
Run Code Online (Sandbox Code Playgroud)
我现在想要将T的约束添加到Enum,例如(我从Stackoverflow文章中获得):where T : struct, IConvertible但是我遇到了问题,因为T需要能够获取可以为空的枚举.错误消息说:
类型'Enums.Animals?' 必须是非可空值类型才能在泛型类型或方法中将其用作参数"T"
有没有办法做到这一点,或者我需要依靠运行时检查我在方法内部?
谢谢大家!
我有一个泛型类Foo<T>,我想约束T为一个enum类型.这可能在C#中吗?
我试过了
public class Foo<T> where T : enum // COMPILATION ERROR
Run Code Online (Sandbox Code Playgroud)
但这种方法似乎只对工作class和struct.
同样,尝试约束T到基础enum类型也不起作用:
public class Foo<T> where T : int // COMPILATION ERROR
Run Code Online (Sandbox Code Playgroud)
因为int不是类或接口.
编辑我现在意识到之前已经发布了类似的问题,最终可以删除这个问题.一个与我的问题更相关的问题,也包含与下面相同的答案,就是这个问题.
更新2018年9月13日在最新的次要C#版本7.3中,现在可以将泛型类型约束为Enum.有关详细信息,请参阅此处.
我想在父抽象类中声明以下内容:
public abstract void RefreshDisplay<TView>(Enum value);
Run Code Online (Sandbox Code Playgroud)
然后将在子类中实现,如:
public override void RefreshDisplay<RxViewModel>(RxViews view)
Run Code Online (Sandbox Code Playgroud)
其中RxViews是枚举,并从该枚举"查看"特定值.
直到运行时才会知道它来自的实际视图和枚举.
可以这样做吗?我很感激帮助.
编辑:我可能会问这个错误.TView不是枚举,而是从ViewModelBase继承的视图.(我不知道这是一个重复的问题?)谢谢.
编辑:我猜这是在4.5中修复的.任何想法如何在net 4.0中解决这个问题?
我创建了以下抽象类:
public abstract class AbstractClass
{
public abstract string Name { get; set; }
public abstract object Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在我想派生两个抽象类的类.我想使用enum而不是类型object.我的派生类看起来像这样:
头等舱:
public class InheritanceClass1:AbstractClass
{
public override string Name { get; set; }
public override FirstEnum Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
二等:
public class InheritanceClass2 : AbstractClass
{
public override string Name { get; set; }
public override SecondEnum Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我的代码中显示错误,属性值的类型不是object.我试着使用new-keyword而不是override …
我想使用 .NET Standard 实现以下方法:
public static void SetFlag<TEnum>(ref TEnum value, TEnum flag)
where TEnum : Enum
Run Code Online (Sandbox Code Playgroud)
我花了几个小时试图实现这一目标:
|对于像 s 这样的基本类型来说,通过反射获取运算符似乎是不可能的enum。dynamic需要引用额外的包 ( Microsoft.CSharp.RuntimeBinder),但我希望我的库保持纯粹的 .NET 标准符合。我最新的想法是手动比较 TEnum每个有效的枚举类型{byte , sbyte, short, ushort, int, uint, long, ulong}。但这感觉真的很奇怪而且肮脏:
try
{
var v = (byte)(object)value | (byte)(object)flag;
value = (TEnum)(object)v;
return;
}
catch (InvalidCastException) { }
try
{
var v = (int)(object)value | (int)(object)flag; …Run Code Online (Sandbox Code Playgroud) 我已经看到 C# 中用于枚举的通用扩展方法的示例where T: struct,还有另一个使用where T: IComparable. 例如,在前一种情况下:
public static class EnumExtensionMethods
{
public static string Description<T>(this T enumValue) where T : struct
{
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
我很困惑为什么约束要求该类型T必须是struct. 我希望它是where T : Enum。谁可以给我解释一下这个?作为奖励项目,也许还可以解释为什么IComparable在某些示例中也使用。
FWIW,我对此进行了研究。我可以找到关于为什么IComparable使用的解释,例如在这个问题中,但它似乎不是决定性的,它们也没有解释为什么struct结合使用。
由于这个问题,我设法弄清楚如何限制我的通用方法仅接受枚举。
现在,我尝试创建一个通用方法,以便可以将下拉列表绑定到我选择的任何枚举,在下拉列表中显示描述,其值等于枚举值的数值。
public static object EnumToDataSource<T>() where T : struct, IConvertible {
if (!typeof(T).IsEnum) // just to be safe
throw new Exception(string.Format("Type {0} is not an enumeration.", typeof(T)));
var q = Enum.GetValues(typeof(T)).Cast<T>()
.Select(x => new { ID = DataUtil.ToByte(x), Description = x.ToString() }) // ToByte() is my own method for safely converting a value without throwing exceptions
.OrderBy(x => x.Description);
return q;
}
Run Code Online (Sandbox Code Playgroud)
看起来不错,但 ToByte() 始终返回 0,即使我的枚举已显式设置值,如下所示:
public enum TStatus : byte {
Active = 1,
Inactive …Run Code Online (Sandbox Code Playgroud) 我有一个3类枚举类
我想有一个方法,可以将所有3个枚举作为参数,并获取枚举的整数值.
public enum Enum1
{
Fire = 0,
Hour_24 = 1,
Key_Switch = 2,
Follower = 3,
Entry_Delay1 = 4,
Entry_Delay2 = 5,
Intertior = 6,
Local_Only = 7,
}
public enum Enum2
{
Faulted = 0,
Tampered = 1,
Trouble = 2,
Bypassed = 3,
Inhibited = 4,
Low_Battery = 5,
Loss_Supervision = 6,
Reserved,
Alarm_Memory = 8,
Bypass_Memory = 9
}
private void BuildMessage ()
{
List<Enum1> Enum1List = new List<Enum1>();
FillBits(Enum1List); // => Here I get …Run Code Online (Sandbox Code Playgroud) 我正在为游戏编写一个寻路算法,但试图保持它的通用性,以便它可以在未来的应用程序中使用.
我有一个Node类,它包含X,Y和"PassableType".
NodeGrid类存储一个节点数组,包含它们如何连接的图形信息,然后有一个FindAStarPath()函数,该函数将"PassableTypes"作为参数StartNode,EndNode和params.
我的问题是确定"PassableType"应该具有什么类型.
理想情况下我想要的是能够使用通用枚举 - 即每个游戏定义的限制列表.Node将保存该列表中的单个元素,以说明它是什么路径类型(当前游戏可能使用Path,Grass,Wall等)
因此,当实体尝试路径时,它提供路径查找功能,其类型被视为"可通过".所以男人可以使用
FindAStarPath(CurrentNode, DestinationNode, "Path", "Floor", "Door");
Run Code Online (Sandbox Code Playgroud)
但是汽车可能会使用
FindAStarPath(StartNode, EndNode, "Road");
Run Code Online (Sandbox Code Playgroud)
我的问题是我无法弄清楚如何让NodeGrid采用Generic枚举或等效逻辑.
目前我已经接受了字符串,但这意味着我
每次使用它时都必须编写MyEnum.Road.ToString().
理想情况下,我想做点什么
NodeGrid<MyEnum> CurrentNodeGrid = new NodeGrid<MyEnum>()
Run Code Online (Sandbox Code Playgroud)
然后Nodes会将MyEnum作为passableType,路径寻找函数也是如此,因此每个游戏都有一组不同的tile类型用于路径.
但我不能将NodeGrid定义为:
public class NodeGrid<T> where T:enum
Run Code Online (Sandbox Code Playgroud)
为清楚起见,使用此枚举的唯一部分路径查找功能是这个(包含在Node中):
public bool IsPassable(string[] passableTypes)
{
for (var i = 0; i < passableTypes.Count(); i++)
{
if (this.PassableType == passableTypes[i]) return true;
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
谢谢Haighstrom
我有一个方法,我用来将字符串转换为通用枚举.可以将结果值分配给可以为空的字段.
对于不可为空的情况,以下工作正常,但我无法弄清楚如何正确调整它以允许可为空的返回类型,比如在参数为null的情况下,或者实际上如何允许返回类型可能是null或不可为空(也许这是不可能的?).每置换Nullable<T>和T?,我试过仍然导致的返回值和方法名称都被红色squiggleys
private static T ConvertStringToEnumValue<T>(string value)
{
// Converts string to a given enum-type T value.
T EnumValue;
try
{
EnumValue = (T)Enum.Parse(typeof(T), value);
if (!Enum.IsDefined(typeof(T), EnumValue))
{
return default(T); // 0 for enum
}
}
catch (Exception e)
{
return default(T); // 0 for enum
}
return EnumValue;
}
Run Code Online (Sandbox Code Playgroud) c# ×10
enums ×7
generics ×5
nullable ×2
.net ×1
constraints ×1
inheritance ×1
linq ×1
reflection ×1