console.cs IsHandleRedirected奇怪

时间:2018-04-22 04:53:23

标签: c# .net winapi

MS'自己的console.cs具有以下函数,由IsInput / Output / ErrorRedirected API使用。

private static bool IsHandleRedirected(IntPtr ioHandle) {

    // Need this to use GetFileType:
    SafeFileHandle safeIOHandle = new SafeFileHandle(ioHandle, false);

    // If handle is not to a character device, we must be redirected:
    int fileType = Win32Native.GetFileType(safeIOHandle);
    if ((fileType & Win32Native.FILE_TYPE_CHAR) != Win32Native.FILE_TYPE_CHAR) // <--- ??
        return true;

    // We are on a char device.
    // If GetConsoleMode succeeds, we are NOT redirected.
    int mode;
    bool success = Win32Native.GetConsoleMode(ioHandle, out mode);
    return !success;
}

我不理解// <--- ??标记(由我)标记的逻辑。 if (fileType != Win32Native.FILE_TYPE_CHAR) return true;会有意义,但我不会理解为什么在比较之前它会被& Win32Native.FILE_TYPE_CHAR掩盖。

为了使其更加混乱,常量FILE_TYPE_CHAR是单个位0x0002,它也由FILE_TYPE_PIPE = 0x0003共享,因此有问题的if语句不会return true; 1}}如果文件句柄引用了一个管道(可能依赖GetConsoleMode后来失败了??)。

任何深入了解代码编写方式的原因都将非常受欢迎。感谢。

1 个答案:

答案 0 :(得分:0)

使用标记枚举时,它曾经是一种常用技术。

您在输入值和要检查的标志之间使用按位,并将结果与​​标志本身进行比较。如果输入值包含标志,则条件为真,否则,条件为假。

让我用一个简单的例子说明:

假设你有这个枚举:

[Flags]
enum test 
{
    None = 0, // 0000
    One = 1,  // 0001
    Two = 2,  // 0010
    Four = 4, // 0100
    Eight = 8 // 1000
}

你有一个想要测试的价值。让我们说13.当您将13转换为四位二进制数时,您得到1101 - 所以您可以这样做:

var input = 13;
if(((test)input & test.One) == test.One) // that's testing if 1101 & 0001 = 0001
{
    // The result of this condition is true, since 13 is an odd number.
}

但是,从.Net 4.0开始,您只需使用HasFlag方法:

if(input.HasFlag(test.One))
{
    // The result of this condition is true, since 13 is an odd number.
}

有关详细信息,请参阅Ending the Great Debate on Enum Flags