C# 使用泛型将字符串值强制转换为枚举时出现混淆,而仅将字符串值强制转换为枚举

C# 使用泛型将字符串值强制转换为枚举时出现混淆,而仅将字符串值强制转换为枚举,c#,generics,C#,Generics,我正在努力理解泛型,当我在观看斯科特·艾伦的一段pluralsight视频时,他展示了丑陋代码与优秀代码的对比 代码,但我不理解下面要提到的内容: public enum Steps { Step1, Step2, Step3 } 丑陋代码示例: Steps value = (Steps)Enum.Parse(typeof(Steps),input); public static class StringExtensions { public static TEnum Pa

我正在努力理解泛型,当我在观看斯科特·艾伦的一段pluralsight视频时,他展示了丑陋代码与优秀代码的对比 代码,但我不理解下面要提到的内容:

public enum Steps
{
  Step1,
  Step2,
  Step3
}
丑陋代码示例:

Steps value = (Steps)Enum.Parse(typeof(Steps),input);
public static class StringExtensions
{
   public static TEnum ParseEnum<TEnum>(this string value)
   {
      return (TEnum)Enum.Parse(typeof(TEnum),value);
   }
}

var input = "Step1";
var value = input.ParseEnum<Steps>();
console.writeline(value);
好的代码和强类型:

Steps value = (Steps)Enum.Parse(typeof(Steps),input);
public static class StringExtensions
{
   public static TEnum ParseEnum<TEnum>(this string value)
   {
      return (TEnum)Enum.Parse(typeof(TEnum),value);
   }
}

var input = "Step1";
var value = input.ParseEnum<Steps>();
console.writeline(value);
公共静态类StringExtensions
{
公共静态TEnum ParseEnum(此字符串值)
{
return(TEnum)Enum.Parse(typeof(TEnum),value);
}
}
var input=“Step1”;
var value=input.ParseEnum();
控制台写入线(值);
但在这里我不明白为什么第二个代码是好的,因为它也做了一个铸造,似乎代码1和2是相同的,或者可能是我没有正确地理解为什么第二个代码是更好的,因为它做相同的类型铸造


有人能解释一下,尽管第二段代码的类型和第一段代码的类型相同,但根据作者的说法,第二段代码是强类型和更好的吗?

我认为这是一个糟糕的例子。我认为第二个代码片段是“好代码”的唯一原因是它符合DRY原则(不要重复)。这是一个通用代码,代码可以写100次,但现在只写一次就可以了

对于泛型部分,这段代码有一些错误。例如,您可以在不是枚举的类型上调用它。而且它并没有真正显示泛型的好处。一个简单得多的例子就可以了

好的代码和强类型

这不是很好的代码,没有什么比第一个示例中的强类型更有效的了。更有甚者,IntelliSense会建议我

var name = "@CamiloTerevinto@".ParseEnum<Fruit>();
var name=“@CamiloTerevinto@”.ParseEnum();
是有效的,但显然不是。事实上,对于这样的场景,该代码甚至没有一个try-catch


总的来说,第二个代码片段只在符合DRY的情况下更好一些,但我不会将其作为扩展方法,也不会将其称为强类型。

我会说扩展方法在使用时提供更好的可读性,我想这就是Scott Allen试图展示的示例。他真的说它是强类型的吗

干式原理是将其放入方法中的另一个优点

此外,我可能会通过检查有效字符串值来扩展它,例如:

public static TEnum ParseEnum<TEnum>(this string enumValue, bool ignoreCase = true) where TEnum : struct
{
    if (!Enum.TryParse(enumValue, ignoreCase, out TEnum result))
    {
        throw new ArgumentException(
            $"{enumValue} is not a valid {typeof(TEnum).Name}",
            typeof(TEnum).Name);
    }

    return result;
}
public static TEnum ParseEnum(此字符串enumValue,bool ignoreCase=true),其中TEnum:struct
{
if(!Enum.TryParse(enumValue、ignoreCase、out TEnum result))
{
抛出新的ArgumentException(
$“{enumValue}不是有效的{typeof(TEnum).Name}”,
类型(TEnum)。名称);
}
返回结果;
}

…但这不是重点。

对我来说,扩展似乎更难看,因为它意味着你可以将每个字符串解析为枚举,而你肯定不能。说到这里,你的问题完全是基于观点的。您应该询问作者,更好的代码对您有何影响。扩展的另一个问题是,您可以将任何类型作为泛型类型传递,代码将编译,但会在运行时抛出。(例如,
input.ParseEnum()
将抛出)我们真的应该回答这个假设某件事情是好的还是坏的做法的问题?这难道不是一个基于意见的问题吗?我怀疑这个问题是否能得到客观的答案。“我想是的,”他说,“我不能完全肯定。OP说它是“强类型”的,而不是,它与第一个版本完全相同。这是可以客观回答的。帕特里克,答案很好way@CamiloTerevinto我同意“强类型”部分的答案很简单,因为它只是whrong。然而,这不是真正的问题,即“为什么它更好”,这意味着它更好,这不能客观地说。@HimBromBeere我只是想从泛型的角度理解第二个代码段是如何强类型的,并且比第一个代码段更好,为什么它不是强类型的,这就是我要尝试的understand@ILoveStackoverflow因为解析永远不能是强类型的。强类型表示您正在使用一个类,因此重命名该类会修复对它的引用。因此,假设问题中提到的代码需要使用强类型,那么需要做什么?仅就我的泛型知识而言,代码示例没有帮助。比较一下。这是一个很好的例子。@ILoveStackoverflow泛型对于这个例子没有帮助,这就是问题所在。正如Patrick提到的,泛型有助于避免使用
对象
而不是类,例如,感谢您为帮助我所付出的努力和宝贵的时间。感谢:)