2009-10-29 24 views
2

基於http://alexreg.wordpress.com/2009/05/03/strongly-typed-csv-reader-in-c/,我創建了一個可以讀取不同文件類型的DLL。我也有成功運行的單元測試。我創建一個結構體並將其用作泛型類型。c#結構字段是「從不分配給」警告

無論如何,當我編譯時,我得到每個結構字段的警告。例如:字段'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; 
     } 
} 
+0

它可能是更容易簡化你的榜樣...... – 2009-10-29 16:38:08

+0

我開始這樣做,但隨後似乎過於簡單化,我想最重要的部分是: fieldTypeInfo .FieldInfo.SetValueDirect(__ makeref(record),fieldValue); – 2009-10-29 16:40:55

+0

重點是:沒有簡單的例子,我們可以'再現你所看到的...所以有點難以滿懷信心地回答。 – 2009-10-29 17:09:16

回答

3

編譯器是從不將能夠發現反射。根據定義,通過使用反射,你已經走到了編譯器之外。

IMO,雖然,這是一個不好的使用結構 - 這看起來非常像它應該對班工作...

+0

你的意思是「它應該在課堂上工作」?該結構嚴格定義記錄字段和字段屬性。也許我應該使用record.AddField(「name」,typeof(int))或類似的東西來創建一個Record類,但我確實喜歡這種簡單和強大的打字。 – 2009-10-29 16:47:13

+0

無論如何,你確實提出了一個關於Reflection的好點。我很困惑,爲什麼我以前沒有得到這個錯誤... – 2009-10-29 16:50:55

+0

結構通常不是爲了表示「記錄」。它們是爲了表示價值 - 例如「26英鎊」等。「記錄」是典型的對象=類。不要誤導;過大的結構可能導致**效率低下。 – 2009-10-29 17:04:52

1

似乎編譯器無法檢測到這種「間接」的賦值。它只能檢測到直接分配,如field=value

你可以反正禁用特定的編譯器警告。假設您正在使用Visual Studio,請參閱:http://msdn.microsoft.com/en-us/library/edzzzth4.aspx

+0

我會同意你的看法,除非這些警告不會提前發佈。在某個時候(我希望我知道什麼時候!),我改變了「打破」了它。我會看看我能不能把它縮小。 – 2009-10-29 16:42:49

0

我討厭當我推倒重來。來自http://www.filehelpers.com/的FileHelpers已經以非常類似的方式做到了這一點,當然也涵蓋了更多邊緣案例。他們讓你定義一個具有屬性而不是結構的類(如Marc所建議的)。如果你將它們的記錄定義設置爲非公開的,你會得到我得到的相同的編譯器警告。

+0

現在我又用了一些,我必須說他們的CSV實現(如最終用戶所見)並不像我的那樣乾淨或容易使用。無論哪種方式,他們都做得很好,可能比我做過的要好。 – 2009-11-05 20:57:56

1

如果使用結構而不是你應該知道你爲什麼這樣做。

一些(罕見)情況下,你應該使用結構:

  1. 的P/Invoke(當本機功能使用「結構」) - 這是(恕我直言)的原因MS添加結構的一個原因.NET(爲了與本地代碼兼容)
  2. 結構體被稱爲值類型。結構應該非常小(例如struct DateTime,結構GpsCoordinates是使用結構而不是類的原因,因爲結構比類更「快」,因爲GC不需要關心它
  3. 如果你不知道該使用什麼:use一流的!

--hfrmobile