简体   繁体   English

c#struct字段“从不分配给”警告

[英]c# struct fields are “never assigned to” warnings

Based on http://alexreg.wordpress.com/2009/05/03/strongly-typed-csv-reader-in-c/ , I created a DLL which can read different file types. 基于http://alexreg.wordpress.com/2009/05/03/strongly-typed-csv-reader-in-c/ ,我创建了一个可以读取不同文件类型的DLL。 I also have unit tests that run successfully. 我也有成功运行的单元测试。 I create a struct and use it as the generic type. 我创建一个结构并将其用作泛型类型。

Anyway, when I compile, I get a warning on each of the struct fields. 无论如何,当我进行编译时,我会在每个struct字段上得到一个警告。 For example: field 'FileReader.Tests.CsvReader.Record.Field1' is never assigned to, and will always have its default value 0 例如:字段'FileReader.Tests.CsvReader.Record.Field1'从未分配给它,并且将始终具有其默认值0

I am in fact setting the value with SetValueDirect() and when I run through the tests or debug the code, I can verify that. 实际上,我是通过SetValueDirect()设置值的,当我运行测试或调试代码时,我可以进行验证。 Why is it giving me that error then, and how can I avoid or fix it? 为什么它会给我该错误,以及如何避免或解决该错误?

Here is some basic code to give you an idea. 这是一些基本的代码可以给您一个想法。 I'm guessing I haven't provided enough, but hopefully someone has a clue. 我猜我还没有提供足够的信息,但希望有人能提供一些线索。

public abstract class FileReader<TRecord> : IDisposable where TRecord : struct
{
        public TRecord? ReadRecord()
        {
            List<string> fields;
            string rawData;

            this.recordNumber++;
            while (this.ReadRecord(this.fieldTypeInfoList.Length, out fields, out rawData))
            {
                try
                {
                    // Insert the current record number to the beginning of the field list
                    fields.Insert(0, this.recordNumber.ToString(CultureInfo.InvariantCulture));

                    // Convert each field to its correct type and set the value
                    TRecord record = new TRecord();
                    FieldTypeInfo fieldTypeInfo;
                    object fieldValue;

                    // Loop through each field
                    for (int i = 0; i < this.fieldTypeInfoList.Length; i++)
                    {
                        fieldTypeInfo = this.fieldTypeInfoList[i];

                        bool allowNull = fieldTypeInfo.AllowNull == null ? this.AllowNull : fieldTypeInfo.AllowNull.Value;
                        if (i >= fields.Count && !allowNull)
                        {
                            // There are no field values for the current field
                            throw new ParseException("Field is missing", this.RecordNumber, fieldTypeInfo, rawData);
                        }
                        else
                        {
                            // Trim the field value
                            bool trimSpaces = fieldTypeInfo.TrimSpaces == null ? this.TrimSpaces : fieldTypeInfo.TrimSpaces.Value;
                            if (trimSpaces)
                            {
                                fields[i] = fields[i].Trim();
                            }

                            if (fields[i].Length == 0 && !allowNull)
                            {
                                throw new ParseException("Field is null", this.RecordNumber, fieldTypeInfo, rawData);
                            }

                            try
                            {
                                fieldValue = fieldTypeInfo.TypeConverter.ConvertFromString(fields[i]);
                            }
                            catch (Exception ex)
                            {
                                throw new ParseException("Could not convert field value", ex, this.RecordNumber, fieldTypeInfo, rawData);
                            }

                            fieldTypeInfo.FieldInfo.SetValueDirect(__makeref(record), fieldValue);
                        }
                    }

                    return record;
                }
                catch (ParseException ex)
                {
                    ParseErrorAction action = (ex.FieldTypeInfo.ParseError == null) ? DefaultParseErrorAction : ex.FieldTypeInfo.ParseError.Value;

                    switch (action)
                    {
                        case ParseErrorAction.SkipRecord:
                            continue;

                        case ParseErrorAction.ThrowException:
                            throw;

                        case ParseErrorAction.RaiseEvent:
                            throw new NotImplementedException("Events are not yet available", ex);

                        default:
                            throw new NotImplementedException("Unknown ParseErrorAction", ex);
                    }
                }
            }

            return null;
        }
}

The compiler is never going to be able to spot reflection. 编译器永远无法发现反射。 By definition, by using reflection you have stepped outside the compiler. 根据定义,通过使用反射,您已走出编译器。

IMO, though, this is a bad use of structs - that looks very much like it should be working on classes... IMO,但是,这是对结构的错误使用-看起来非常像它应该在类上工作...

It seems that the compiler is not capable of detecting such "indirect" assignments. 似乎编译器无法检测到这种“间接”分配。 It can only detect direct assignments like field=value . 它只能检测直接分配,例如field=value

You can anyway disable specific compiler warnings. 您仍然可以禁用特定的编译器警告。 Assuming that you are using Visual Studio, see here: http://msdn.microsoft.com/en-us/library/edzzzth4.aspx 假设您使用的是Visual Studio,请参见此处: http : //msdn.microsoft.com/zh-cn/library/edzzzth4.aspx

If using struct instead of class you should know why you do it. 如果使用struct而不是class,您应该知道为什么这么做。

Some (rare) cases where you should use struct: 在某些(罕见)情况下,应使用struct:

  1. P/Invoke (when the native function uses "structs") - this is (imho) one of the the reason why MS added struct to .NET (in order to be compatible with native code) P /调用(当本机函数使用“结构”时)-这是(imho)MS向.NET添加结构(以与本机代码兼容)的原因之一。
  2. structs are so called value types. 结构就是所谓的值类型。 structs should be very small (eg struct DateTime, struct GpsCoordinates are reasons using struct instead of classes since struct are "faster" than classes because the GC need not to care about it 结构应该非常小(例如struct DateTime,struct GpsCoordinates是使用struct而不是类的原因,因为struct比类“更快”,因为GC无需关心它
  3. If you don't know what to use: use class!! 如果您不知道该使用什么,请使用class!

--hfrmobile --hfrmobile

I hate when I reinvent the wheel. 我讨厌重新发明轮子。 FileHelpers from http://www.filehelpers.com/ already does this in a very similar way and of course covers more edge cases. 来自http://www.filehelpers.com/的 FileHelpers已经以非常相似的方式执行此操作,并且当然涵盖了更多的极端情况。 They have you define a class with attributes instead of a struct (as Marc suggested). 他们让您使用属性而不是结构来定义类(如Marc建议的那样)。 If you set their record definition as non-public, you get the same compiler warnings I was getting. 如果将其记录定义设置为非公开,则会收到与我相同的编译器警告。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM