Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.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# 字段“field”从未指定给,并且始终具有其默认值_C#_Resharper_Pinvoke - Fatal编程技术网

C# 字段“field”从未指定给,并且始终具有其默认值

C# 字段“field”从未指定给,并且始终具有其默认值,c#,resharper,pinvoke,C#,Resharper,Pinvoke,正在将结构初始化为默认值: private struct TOKEN_USER { internal SID_AND_ATTRIBUTES User; //Compiler warning comes from here. } [StructLayout(LayoutKind.Sequential)] private struct SID_AND_ATTRIBUTES { internal IntPtr Sid; private

正在将结构初始化为默认值:

private struct TOKEN_USER
    {
        internal SID_AND_ATTRIBUTES User; //Compiler warning comes from here.
    }

[StructLayout(LayoutKind.Sequential)]
private struct SID_AND_ATTRIBUTES
   {
       internal IntPtr Sid;
       private int Attributes;
   }
然后进行两个必需的调用以检索指向该结构的指针: 与使用此选项的问题无关:

TOKEN_USER tokenUser = default(TOKEN_USER);
然后编组回一个结构

GetTokenInformation(tokenhandle, TokenInformationClass.TokenUser, sid, sidlength, ref sidlength);
这是可行的,但是编译器警告我TOKEN_User中的“User”字段未分配

R建议我从构造函数初始化它:

tokenUser = (TOKEN_USER)Marshal.PtrToStructure(sid, tokenUser.GetType());
但是,这不会编译,因为错误构造函数无法调用自身。 我的问题是,我应该只将其分配给SID_和_属性default以满足编译器的要求,还是忽略它

测试程序:

public TOKEN_USER(SID_AND_ATTRIBUTES user) : this(user)
        {
        }

每当您使用通过某种外部机制(如反射或封送处理类)初始化的类型时,都会看到此警告。问题是编译器无法知道该字段是如何初始化的;它只能看到类型本身,而类型中没有任何东西可以初始化该字段

由于声明一个从未赋值的字段通常是一个编码错误,编译器会针对这种情况生成警告

我不确定确切的建议R是什么,但显然不能使用与您声明的相同的构造函数重载,因为这将创建无限递归初始化

在某些情况下,使用以下命令初始化结构是有意义的:即调用默认构造函数,但这是为了处理需要访问构造函数中的字段或属性,并且在初始化之前无法访问的问题:调用此构造函数初始化整个对象。也许R就是这么想的

无论如何,在这种情况下,我的方法只是禁用警告,因为我确信这是一个误报。我确实初始化了字段,只是不是以编译器知道的方式初始化的。您可以通过pragma警告指令来实现这一点。例如:

   [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr OpenProcess(
        int dwDesiredAccess,
        [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
        int dwProcessId);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool OpenProcessToken(
        IntPtr processHandle,
        int desiredAccess,
        ref IntPtr TokenHandle);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool GetTokenInformation(
        IntPtr tokenHandle,
        TokenInformationClass tokenInformationClass,
        IntPtr tokenInformation,
        int TokenInformationLength,
        ref int ReturnLength);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool IsValidSid(
        IntPtr SID);


    private enum TokenInformationClass
    {
        TokenUser = 1,
    }

    private const int QueryInformation = 0x400;

    private const int TokenRead = 0x20008;

    private struct TOKEN_USER
    {
        internal SID_AND_ATTRIBUTES User; //Compiler warning comes from here.
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct SID_AND_ATTRIBUTES
    {
        internal IntPtr Sid;
        private int Attributes;
    }



    internal static IntPtr GetProcessHandle()
    {
        foreach (Process p in Process.GetProcesses())
        {
            using (p)
            {
                if (p.ProcessName == "explorer")
                {
                    return OpenProcess(QueryInformation, false, p.Id);
                }
            }
        }
        return IntPtr.Zero;
    }

    public void Test()
    {
        IntPtr pHandle = GetProcessHandle();

        IntPtr tokenHandle = IntPtr.Zero;
        OpenProcessToken(pHandle, TokenRead, ref tokenHandle);

        int sidlength = 0;
        GetTokenInformation(tokenHandle, TokenInformationClass.TokenUser, IntPtr.Zero, 
0, ref sidlength);

        TOKEN_USER tokenUser = default(TOKEN_USER);
        IntPtr sid = Marshal.AllocHGlobal(sidlength);

        GetTokenInformation(tokenHandle, TokenInformationClass.TokenUser,sid, 
sidlength, ref sidlength);

        tokenUser = (TOKEN_USER)Marshal.PtrToStructure(sid, tokenUser.GetType());


        if (IsValidSid(tokenUser.User.Sid))
        {
            Debug.WriteLine("Valid!");
        }
    }

请参阅的答案中的相关讨论。在这里,建议您添加一条注释,解释为什么禁用警告以及为什么禁用警告是安全的;总之,在禁用警告的任何情况下,这都是一个非常好的主意。

当您使用通过某种外部机制初始化的类型(如反射或此处的封送处理类)时,都会看到此警告。问题是编译器无法知道该字段是如何初始化的;它只能看到类型本身,而类型中没有任何东西可以初始化该字段

由于声明一个从未赋值的字段通常是一个编码错误,编译器会针对这种情况生成警告

我不确定确切的建议R是什么,但显然不能使用与您声明的相同的构造函数重载,因为这将创建无限递归初始化

在某些情况下,使用以下命令初始化结构是有意义的:即调用默认构造函数,但这是为了处理需要访问构造函数中的字段或属性,并且在初始化之前无法访问的问题:调用此构造函数初始化整个对象。也许R就是这么想的

无论如何,在这种情况下,我的方法只是禁用警告,因为我确信这是一个误报。我确实初始化了字段,只是不是以编译器知道的方式初始化的。您可以通过pragma警告指令来实现这一点。例如:

   [DllImport("kernel32.dll", SetLastError = true)]
    private static extern IntPtr OpenProcess(
        int dwDesiredAccess,
        [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
        int dwProcessId);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool OpenProcessToken(
        IntPtr processHandle,
        int desiredAccess,
        ref IntPtr TokenHandle);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool GetTokenInformation(
        IntPtr tokenHandle,
        TokenInformationClass tokenInformationClass,
        IntPtr tokenInformation,
        int TokenInformationLength,
        ref int ReturnLength);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool IsValidSid(
        IntPtr SID);


    private enum TokenInformationClass
    {
        TokenUser = 1,
    }

    private const int QueryInformation = 0x400;

    private const int TokenRead = 0x20008;

    private struct TOKEN_USER
    {
        internal SID_AND_ATTRIBUTES User; //Compiler warning comes from here.
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct SID_AND_ATTRIBUTES
    {
        internal IntPtr Sid;
        private int Attributes;
    }



    internal static IntPtr GetProcessHandle()
    {
        foreach (Process p in Process.GetProcesses())
        {
            using (p)
            {
                if (p.ProcessName == "explorer")
                {
                    return OpenProcess(QueryInformation, false, p.Id);
                }
            }
        }
        return IntPtr.Zero;
    }

    public void Test()
    {
        IntPtr pHandle = GetProcessHandle();

        IntPtr tokenHandle = IntPtr.Zero;
        OpenProcessToken(pHandle, TokenRead, ref tokenHandle);

        int sidlength = 0;
        GetTokenInformation(tokenHandle, TokenInformationClass.TokenUser, IntPtr.Zero, 
0, ref sidlength);

        TOKEN_USER tokenUser = default(TOKEN_USER);
        IntPtr sid = Marshal.AllocHGlobal(sidlength);

        GetTokenInformation(tokenHandle, TokenInformationClass.TokenUser,sid, 
sidlength, ref sidlength);

        tokenUser = (TOKEN_USER)Marshal.PtrToStructure(sid, tokenUser.GetType());


        if (IsValidSid(tokenUser.User.Sid))
        {
            Debug.WriteLine("Valid!");
        }
    }

请参阅的答案中的相关讨论。在这里,建议您添加一条注释,解释为什么禁用警告以及为什么禁用警告是安全的;嗯,在禁用警告的任何情况下,这都是一个非常好的主意。

您能显示完整的警告吗program@DavidHeffernan完整的程序太多,无法缩减,所以我创建了一个测试程序来演示这个问题,我使用了一个流程令牌,所以我创建了一个helper函数来返回explorer进程令牌进行演示。tokenUser=defaultTOKEN\u USER的意义是什么?稍后将分配给tokenUser。编译器对象是哪一行代码?初始化为默认值以获取tokenUser=TOKEN\u usermarshall.PtrToStructuresid,tokenUser.GetType中的类型;编译器将对象指向结构字段本身。内部SID_和_属性用户;不要那样做。你能出示一份完整的表格吗program@DavidHeffernan完整的程序太大,无法缩减,所以我创建了一个测试程序来演示这个问题,我使用了一个进程令牌,所以我创建了一个帮助函数来返回explorer进程令牌进行演示。tokenUser=defaultTOKEN\u USER的意义是什么?稍后将分配给tokenUser。编译器对象是哪一行代码?初始化为默认值以获取tokenUser=TOKEN\u usermarshall.PtrToStructuresid,tokenUser.GetType中的类型;编译器将对象指向结构字段本身。内部SID_和_属性用户;不要那样做。做典型
eofTOKEN_用户。谢谢!我从来没用过pragma。。。很高兴知道。是的,R确实建议我发布一段不可编译的代码,我想把它报告为一个bug…谢谢!我从来没用过pragma。。。很高兴知道。是的,R确实暗示了我发布的不可编译代码片段,我正考虑将其报告为bug。。。