Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我如何告诉编译器我的泛型肯定会允许“|=”或强制转换为int?_C#_Generics - Fatal编程技术网

C# 我如何告诉编译器我的泛型肯定会允许“|=”或强制转换为int?

C# 我如何告诉编译器我的泛型肯定会允许“|=”或强制转换为int?,c#,generics,C#,Generics,我是C语言中泛型的新手,我正在尝试创建一个使用泛型的方法。在尝试创建局部变量时,我遇到了where关键字,因此我确信它将成为解决方案的一部分 原因是我有几个不同的枚举变量,但该方法会对每个给定的字符串(该字符串是枚举定义的值之一)执行相同的操作,将其打开,使用类似于位字段的枚举 我把其中的大部分放在一起,我现在陷入困境的部分是能够告诉泛型方法允许|=是可以的,因为我确定传入的任何类型都将支持操作符 如果可能的话,我希望能够保持通用性,因此可以是枚举或列表,并且我将根据类型执行不同的代码路径 我正

我是C语言中泛型的新手,我正在尝试创建一个使用泛型的方法。在尝试创建局部变量时,我遇到了where关键字,因此我确信它将成为解决方案的一部分

原因是我有几个不同的枚举变量,但该方法会对每个给定的字符串(该字符串是枚举定义的值之一)执行相同的操作,将其打开,使用类似于位字段的枚举

我把其中的大部分放在一起,我现在陷入困境的部分是能够告诉泛型方法允许|=是可以的,因为我确定传入的任何类型都将支持操作符

如果可能的话,我希望能够保持通用性,因此可以是枚举或列表,并且我将根据类型执行不同的代码路径

我正在做的事情的例子

enum someType { value1 = 1<<0, value2 = 1<<1, value3 = 1<<2 }; // and so on
// some more enums

private T someMethod<T>(string myIdentifyers) 
    where T: new()
{
    // suppose myIdentifiers is 1 more more of the valid enum options
    // assume that the correct strings and enum combinations will be passed
    T retval = new T();

    while () {
    // assume a loop with a method call that parses off one identifyer at a time
        // if I have to convert the enum to an int first, so be it, but
        // at this point I can't tell it that a cast to int exists
        retval |= (T)System.Enum.Parse( typeof(T), oneIdentifyer, false );
    }

    return retval;
}

一般来说,在泛型类型上调用运算符没有好方法,尽管在某些情况下有一些困难和解决方法可以提供帮助

见类似问题:


在本例中,由于您知道枚举从int到int的转换,我认为Bruno的方法是可行的。

从C4开始,不可能表示枚举通用约束。也不可能表示运算符约束

也就是说,我认为您正在寻找这样一种方法:

public static T AssembleFlagsEnum<T>(IEnumerable<string> names) where T : struct
{
    return (T)(object)names.Aggregate(0, 
       (valSoFar, name) => valSoFar | Convert.ToInt32(Enum.Parse(typeof(T), name)));
}

请注意,这不会验证该类型是否为[Flags]枚举。它也不适用于具有除int以外的底层类型的枚举。

我将尝试类似以下伪代码的方法:

[Flags]
enum someType { value1 = 1<<0, value2 = 1<<1, value3 = 1<<2 }; // and so on
// some more enums

private T someMethod<T>(string myIdentifyers) 
    where T: struct, new()
{
           // check if enum
    if (typeof(T).BaseType != typeof(Enum)) // we should probably check for the flags attribute too
            throw new Exception();

    // suppose myIdentifiers is 1 more more of the valid enum options
    // assume that the correct strings and enum combinations will be passed
    int retval = 0;

    while () {
    // assume a loop with a method call that parses off one identifyer at a time
        // if I have to convert the enum to an int first, so be it, but
        // at this point I can't tell it that a cast to int exists
        retval |= (int) (object) System.Enum.Parse( typeof(T), oneIdentifyer, false );
    }

    return (T) (object) retval;
}

不幸的是,这是不可能的

您可以使用struct约束来限制值类型,但显然它包含的不止是整数。然后,您唯一可以做的就是在代码的早期检查实际类型

支持的约束条件在中进行了描述


您不能执行运算符约束-请参见

如果将枚举someType用作一组位标志,则应使用[Flags]属性标记该枚举someType。@asawyer我是否只需将[Flags]放在每个枚举声明之前?请参见Bruno Silva的回答,他标记了枚举。在这种特殊情况下,您可能还需要查看:-基本上,.net支持标志枚举解析,以逗号分隔的值表示。因此,您只需从MyIdentifier创建字符串,并将其传递给Enum.TryParseSo即可。。。如果我再次打破它:-对于几个枚举,我是在每个枚举之前放置[Flags],还是在声明列表的开头显示[Flags]就足够了?您应该将其放置在每个枚举声明之前。谢谢,这是一个很大的帮助。一个可能很明显的警告是,如果为枚举指定不同的基础类型,例如枚举someType:byte,这将在运行时失败,就像@Ani提到的解决方案一样。希望这不是问题,但值得注意。@Weeble值得注意,但今天不会给我带来问题。