2014-09-11 71 views
0

我在我的程序中有大約20個字段的情況。所有這些都是字符串。現在我還有一個大小爲20的字符串數組。我想從存儲在這個數組中的字符串中依次初始化這些字段。我不想這樣做:當存儲在數組中時,C#字段不保留值

field1 = array [0];

field2 = array [1];

....

field20 = array [19];

所以我寫了這樣的測試程序,但它不適用於字符串。它只適用於參考類型。有什麼辦法可以做到嗎?

public class Program 
{ 
    private string name; 
    private string id; 

    private void Func() 
    { 
     var array = new[] {name, id}; 
     for (int i = 0; i < array.Length; i++) 
     { 
      array[i] = "some string"; 
     } 
    } 

    public static void Main(string[] args) 
    { 
     var p = new Program(); 
     p.Func(); 
     Console.WriteLine(p.name); // prints null 
    } 
} 
+1

你可以通過使用反射,但你不應該。在這個assigment中:'array [i] =「some string」;''拋棄舊的引用,併爲'array [i]'賦值一個新值,這就是爲什麼它不會改變'name '。 – 2014-09-11 08:05:59

+0

@ user2864740 - 好的。你能告訴如何爲p對象賦值數組中的相應字符串值嗎? – VVV 2014-09-11 08:06:03

+1

爲什麼降價?這是正確的初學者問題... – 2014-09-11 08:06:10

回答

3

有關行爲的假設是不正確的。

// Create a NEW array with the specified expressions which are evaluated 
// immediately (to the current values of the fields).. 
var array = new[] {name, id}; 

// Meaning it is equivalent to this .. note that the field names have 
// NOTHING to do with the array object itself. 
var array = new[] {(string)null, (string)null}; 

// Then for each item in the array, assign it a value 
// (replacing what was already there anyway) 
for (int i = 0; i < array.Length; i++) { 
    array[i] = "some string"; 
} 

最後我們最終得到了一個看起來像["some string", "some string"]的數組。再一次,與領域沒有「聯繫」。這個問題與參考類型無關(字符串是也參考類型)。

最好的(而且通常是正確的)方法是誠實地以不同的方式做到這一點。雖然人們可以換場接入/ setter和總有反射。如果是真正所需的動態名稱那麼字典或類似的或許應該被用來代替


下面是一個使用代理服務器的方法來包裝賦值操作。本示例使用Actions和"Statement Lambda" syntax

var setters = new Dictionary<string, Action<Program, string>>() { 
    { "name", (p, value) => p.name = value }, 
    { "id", (p, value) => p.id = value }, 
}; 

// For each field setter, assign a value (could use the name as a look-up) 
foreach (var setter in setters.Values) { 
    setter(this, "some string"); 
} 

這工作,因爲setter(..)調用先前定義的實際行動分配給相應的成員。使用這種查找/代理(使用動作,函數或更復雜的類型)對於某些情況是有效的方法,但在不需要時應該避免。


可以也可以用Reflection完成。

var t = this.GetType(); 
var fieldNames = new [] { "name", "id" }; 
var bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance; 
foreach (var name in fieldNames) { 
    var fieldInfo = t.GetField(name, bindingFlags); 
    fieldInfo.SetValue(this, "some string"); 
} 

反射通常應該是「最後的方法」。它丟失了靜態的輸入信息,將許多錯誤排除在運行時間之外,並且帶來了性能損失(這是可能的並不重要)。有一些非常漂亮的事情可以完成(特別是當表達式和註解也被使用時)..但反射是最好的,直到真正需要時才離開。

+0

沒問題。我可以看到它爲什麼不起作用。不過,我想知道一種有效的方法。你知道嗎? – VVV 2014-09-11 08:10:57

+0

我明白你的解釋。我現在可以看到爲什麼它不起作用。但我想知道解決上述問題的初始化字段與corressponding數組的值。 – VVV 2014-09-11 08:12:39

+0

@ user2864740 - 好的謝謝。 – VVV 2014-09-11 08:13:04

2

看看這是你想達到什麼目的:

public class Program 
{ 
    private string name; 
    private string id; 
    private Dictionary<string, int> mapper = new Dictionary<string, int>(); 
    private String[] array= null; 
    public Program() 
    { 
     mapper.Add("name", 1); 
     mapper.Add("id", 2); 
    } 


    public string Name 
    { 
     get { return array[mapper["name"]]; } 
    } 

    public string Id 
    { 
     get { return array[mapper["id"]]; } 
    } 

    private void Func() 
    { 
     array = new[] { name, id }; 

     for (int i = 0; i < array.Length; i++) 
     { 
      array[i] = "some string"; 
     } 
    } 

    public static void Main(string[] args) 
    { 
     var p = new Program(); 
     p.Func(); 
     Console.WriteLine(p.name); // prints null 
    } 
} 
+0

有一個映射器在這裏是一個開銷,但這是我能想到的最好的。 – Prashant19sep 2014-09-11 08:31:27

相關問題