C# c“结构字段为”;从未分配给;警告

C# c“结构字段为”;从未分配给;警告,c#,generics,struct,C#,Generics,Struct,基于,我创建了一个DLL,可以读取不同的文件类型。我也有成功运行的单元测试。我创建一个结构并将其用作泛型类型 无论如何,当我编译时,我在每个struct字段上都会得到一个警告。例如:字段“FileReader.Tests.CsvReader.Record.Field1”从未分配给,并且其默认值始终为0 事实上,我正在使用SetValueDirect()设置值,当我运行测试或调试代码时,我可以验证这一点。为什么它会给我这个错误,我怎样才能避免或修复它 下面是一些基本代码,让您了解一些情况。我猜我没

基于,我创建了一个DLL,可以读取不同的文件类型。我也有成功运行的单元测试。我创建一个结构并将其用作泛型类型

无论如何,当我编译时,我在每个struct字段上都会得到一个警告。例如:字段“FileReader.Tests.CsvReader.Record.Field1”从未分配给,并且其默认值始终为0

事实上,我正在使用SetValueDirect()设置值,当我运行测试或调试代码时,我可以验证这一点。为什么它会给我这个错误,我怎样才能避免或修复它

下面是一些基本代码,让您了解一些情况。我猜我没有提供足够的信息,但希望有人能提供线索

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;
        }
}
公共抽象类FileReader:IDisposable其中TRecord:struct
{
公共TRecord?ReadRecord()
{
列表字段;
字符串原始数据;
这个.recordNumber++;
while(this.ReadRecord(this.fieldTypeInfoList.Length,out fields,out rawData))
{
尝试
{
//将当前记录编号插入字段列表的开头
插入(0,this.recordNumber.ToString(CultureInfo.InvariantCulture));
//将每个字段转换为正确的类型并设置值
TRecord记录=新的TRecord();
FieldTypeInfo FieldTypeInfo;
对象字段值;
//循环遍历每个字段
for(int i=0;i=fields.Count&&!allowNull)
{
//当前字段没有字段值
抛出新的ParseException(“字段丢失”,this.RecordNumber,fieldTypeInfo,rawData);
}
其他的
{
//修剪字段值
bool trimSpaces=fieldTypeInfo.trimSpaces==null?this.trimSpaces:fieldTypeInfo.trimSpaces.Value;
如果(修剪空间)
{
字段[i]=字段[i].Trim();
}
if(字段[i].Length==0&&!allowNull)
{
抛出新的ParseException(“字段为空”,this.RecordNumber,fieldTypeInfo,rawData);
}
尝试
{
fieldValue=fieldTypeInfo.TypeConverter.ConvertFromString(字段[i]);
}
捕获(例外情况除外)
{
抛出新的ParseException(“无法转换字段值”,例如,this.RecordNumber、fieldTypeInfo、rawData);
}
fieldTypeInfo.FieldInfo.SetValueDirect(_makeref(记录),fieldValue);
}
}
返回记录;
}
捕获(解析异常)
{
ParseErrorAction动作=(ex.FieldTypeInfo.ParseError==null)?DefaultParseErrorAction:ex.FieldTypeInfo.ParseError.Value;
开关(动作)
{
案例ParseErrorAction.SkipRecard:
持续
案例ParseErrorAction.ThroweException:
投
案例ParseErrorAction.RaiseEvent:
抛出新的NotImplementedException(“事件尚不可用”,例如);
违约:
抛出新的NotImplementedException(“未知的ParseErrorAction”,ex);
}
}
}
返回null;
}
}

编译器似乎无法检测此类“间接”赋值。它只能检测直接赋值,如
field=value

您仍然可以禁用特定的编译器警告。假设您使用的是Visual Studio,请参见此处:

编译器永远无法发现反射。根据定义,通过使用反射,您已经走出了编译器


不过,在我看来,这是对结构的一个糟糕的使用——看起来它应该在类上工作……

我讨厌重新发明轮子。来自的FileHelper已经以非常类似的方式完成了这项工作,当然还涵盖了更多的边缘案例。他们让你用属性而不是结构来定义一个类(正如Marc所建议的)。如果将它们的记录定义设置为非公共,则会得到与我相同的编译器警告。

如果使用struct而不是class,您应该知道为什么要这样做

在某些(罕见)情况下,您应该使用struct:

  • P/Invoke(当本机函数使用“structs”时)——这是MS将struct添加到.NET的原因之一(imho)(为了和本机代码兼容)
  • 结构是所谓的值类型。结构应该非常小(例如,struct DateTime、struct GpsCoordinates是使用struct而不是类的原因,因为struct比类“快”,因为GC不需要关心它
  • 如果你不知道使用什么:使用class

  • --hfrmobile

    简化您的示例可能会更容易…我开始这样做,但后来它似乎过于简化了。我认为最重要的部分是:fieldTypeInfo.FieldInfo.SetValueDirect(u makeref(记录),field