简体   繁体   English

字段“ FIELD”从未分配,并且将始终具有其默认值

[英]field 'FIELD' is never assigned to, and will always have its default value

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;
   }

Initializing the structure to default: 将结构初始化为默认值:

TOKEN_USER tokenUser = default(TOKEN_USER);

Then making the two required calls to retrieve the pointer to the structure: (not relevant to the question) using this: 然后使用以下命令进行两个必需的调用以检索指向结构的指针:(与问题无关):

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

and then marshalling back to a structure. 然后编组回一个结构。

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

which works, but the compiler warns me that the 'User' field in TOKEN_USER is unassigned. 可以,但是编译器警告我未分配TOKEN_USER中的“用户”字段。

R# suggests me initializing it from the constructor: R#建议我从构造函数初始化它:

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

However, this doesn't compile, with error "Constructor cannot call itself". 但是,它无法编译,并显示错误“构造函数无法调用自身”。 My question is, should i just assign it to SID_AND_ATTRIBUTES (default) to meet the compiler's requirement, or ignore it? 我的问题是,我应该将其分配给SID_AND_ATTRIBUTES(默认值)以满足编译器的要求,还是忽略它?

Test program: 测试程序:

   [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!");
        }
    }

You will see this warning any time that you use types which are initialized via some external mechanism, such as reflection or (as here) the Marshal class. 每当您使用通过某种外部机制初始化的类型(例如反射或Marshal类)时,都会看到此警告。 The issue is that the compiler has no way to know how that field is initialized; 问题是编译器无法知道该字段是如何初始化的。 all it can see is the type itself, and there is nothing in the type that would initialize that field. 它所能看到的只是类型本身,而类型中没有任何东西可以初始化该字段。

Since declaring a field which is never assigned a value is often a coding mistake, the compiler generates a warning for the case. 由于声明从未分配任何值的字段通常是编码错误,因此编译器会针对这种情况生成警告。

I'm not sure what the exact suggestion R# was, but obviously you can't use the same constructor overload as the one you're declaring, because that would create an infinitely recursive initialization. 我不确定确切的建议R#是什么,但是显然您不能使用与所声明的相同的构造函数重载,因为这将创建无限递归的初始化。

In some cases, it makes sense to initialize the struct using : this() (ie calling the default constructor), but that's for dealing with issues where you want to access a field or property in the constructor and you can't until it's initialized (calling the this() constructor initializes the entire object). 在某些情况下,使用: this()初始化struct是有意义的: this() (即调用默认构造函数),但这是为了处理您要访问构造函数中的字段或属性的问题,除非您对其进行了初始化(调用this()构造函数将初始化整个对象)。 Maybe that's what R# was "thinking" of? 也许这就是R#的想法?


Anyway, my approach in this situation is simply to disable the warning, as I know for sure it's a false positive. 无论如何,在这种情况下,我的方法只是禁用警告,因为我确定这是一个误报。 I do initialize the field, just not in a way that the compiler knows about. 确实对字段进行了初始化,只是没有以编译器知道的方式进行初始化。 You can accomplish this with the #pragma warning directive. 您可以使用#pragma warning指令来完成此操作。 Eg: 例如:

private struct TOKEN_USER
{
    #pragma warning disable 0649
    internal SID_AND_ATTRIBUTES User;
    #pragma warning restore 0649
}

See related discussion at the answer to Suppressing “is never used” and “is never assigned to” warnings . 请参阅有关抑制“从不使用”和“从不分配给”警告的答案的相关讨论。 There, it is suggested that you include a comment explaining why the warning is being disabled and why that's safe; 建议您在此处添加注释,以解释为什么禁用警告以及为什么这样做安全; IMHO, that's a very good idea in any situation where you disable a warning. 恕我直言,在禁用警告的任何情况下,这都是一个好主意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 字段从未分配给它,并且将始终具有其默认值 - Field is never assigned to, and will always have its default value 警告:永远不会将字段分配给,并且始终将其默认值设置为null - Warning: Field is never assigned to, and will always have its default value null 字段'xxx'永远不会分配给,并且将始终具有其默认值null - Field 'xxx' is never assigned to, and will always have its default value null 永远不会将字段xxx分配给,并始终将其默认值设置为null - Field xxx is never assigned to, and will always have its default value null 字段…永远不会分配给它,并且其默认值始终为null - Field … is never assigned to, and will always have its default value null 该字段永远不会分配给它,并且其默认值始终为null - The Field Is Never Assigned To And Will Always Have Its Default Value null 字段从未分配给它,并且将始终具有其默认值null - Field is never assigned to, and will always have its default value null 字段modifyDate永远不会分配给,并且始终具有其默认值0 - Field modifyDate is never assigned to, and will always have its default value 0 构造函数DI - Field永远不会分配给,并且始终具有其默认值 - Constructor DI - Field is never assigned to, and will always have its default value 字段永远不会分配给,并且始终具有默认值0 - Field is never assigned to and will always have its default value 0
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM