8

C# 笨問題 - 唯讀的 ICollection 屬性為什麼能設定初始值?

 1 year ago
source link: https://blog.darkthread.net/blog/readonly-collection-initializer/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

唯讀的 ICollection 屬性為什麼能設定初始值?-黑暗執行緒

一時糊塗,被一段程式迷惑。

Foo 類別的 ICollection<string> 屬性設成 { get; } 唯讀,嘗試將 Items 設成某個 List<string> 編譯出錯完全合理,但為什麼用 Items = { "Item3", "Item4" } 指定初始值卻可以過關?

void Main()
{
	var list = new List<string> {
		"Item1", "Item2"
	};
	var foo1 = new Foo {
	    // Compiler Erro: cannot be assigned to -- it is read only
		Items = list 
	};
	var foo2 = new Foo 
	{
		Items = {
			"Item3", "Item4"
		}
	};	
}
public class Foo 
{
	public ICollection<string> Items { get; } = new List<string>();
}

Fig1_638111561783927592.png

RTFM,本草綱目有記載,Collection Initializer 可用來初始化有實作 IEnumerable 且有 Add() 方法的集合屬性,取代反覆呼叫多次加入初值。支援的 Add() 有兩種:Add(TValue) 及 Add(TKey, TValue),也就是我們平常可以用它指定 List<T>、T[]、Dictionary<K,V> 初始值的原因。

換言之,Collection Initializer 用 = 指派內容,背後是靠反覆呼叫 Add 方法,而非覆寫屬性內容。如此便能解釋為什麼 ICollection<string> Items { get; } 雖是唯讀屬性,C# 背後用 Items.Add("Item3")、Items.Add("Item4") 仍可完成初始值設定。

用 LINQPad 的 IL Code 反組譯功能證明!

Fig2_638111561789039635.png


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK