Ответ 1
Это не будет работать, потому что вы объявили словарь как Dictionary<string, object>
.
Вместо этого вы можете попробовать Dictionary<string, dynamic>
.
Я здесь схожу. Вероятно, потому, что я пропустил какое-то правило, но если так, то, пожалуйста, скажите мне.
Я пытаюсь создать Dictionary
с строкой для ключа и анонимным объектом в качестве значения. Или, на самом деле, я не просто пытаюсь, я это делаю. Но когда я хочу изменить конкретный параметр в объекте, он идет не так.
Я объявляю словарь следующим образом:
var areas = new Dictionary<string, object>
{
{"Key1", new {name = "Name1", today = 0, all = 0}},
{"Key2", new {name = "Name2", today = 0, all = 0}},
...
}
И тогда я предполагаю, что смогу это сделать:
foreach (var area in areas.Keys.ToArray())
{
var areaname = areas[area].name;
}
но Visual Studio не соглашается и отказывается компилировать. Если я пишу это, все работает так, как я думаю, но это на самом деле не помогает мне, это просто делает меня более расстроенным.
var areaname = new
{
name = "Nametest", today = 0, all = 0
};
var testname = areaname.name;
Что я делаю не так? Почему это не работает для меня? Это просто невозможно сделать?
Спасибо за все ваши ответы, они, конечно, немного разобрались! Я думаю, что, возможно, я запутал объект типа с идеей объектов, то есть классов, в С# из-за разочарования. Я переосмыслил весь дизайн и, возможно, сделаю что-то совершенно другое, вместо того, чтобы использовать злые или грязные решения. Хотя интересно, я не думаю, что мои отношения с С# еще не развились!
Это не будет работать, потому что вы объявили словарь как Dictionary<string, object>
.
Вместо этого вы можете попробовать Dictionary<string, dynamic>
.
Это не компилируется, потому что значения в вашем словаре имеют тип object
а object
не содержит name
свойства.
Если вы используете.NET 4, вы можете изменить тип с object
на dynamic
.
Сказав это, я категорически не согласен с этим проектным решением. Вы действительно должны создать класс для этого.
Это не будет работать, потому что вы объявили словарь как Dictionary<string, object>
.
С# создает новый тип в фоновом режиме для вас (к которому вы не можете получить доступ), который имеет эти свойства (при этом известный как анонимный тип). Единственный раз, когда вы можете использовать его напрямую, - это когда он все еще является типом var
- как только вы добавляете его в этот словарь, он прикладывается к object
и, следовательно, вы больше не можете обращаться к свойствам.
Опция 1
Вместо этого вы можете попробовать Dictionary<string, dynamic>
. Dynamic сможет получить доступ к этим свойствам, но это поддерживается только в С#/.NET 4.0
Вариант 2
Вы можете вернуть тип с помощью техники, известной как демонстрация (например, на примере). Это не задокументированная функция, расточительна и немного взломана. Это ужасный злой трюк - особенно потому, что он не будет работать через собрания.
public static T Demonstrate<T>(this T demonstration, object value)
{
return (T)value;
}
Затем вы можете получить доступ к исходным свойствам следующим образом:
var area = new { name = "", today = 0, all = 0 }.Demonstrate(areas[name]);
var areaName = value.name;
Вариант 3 Это, честно говоря, лучший способ
Напишите класс. Если вам нравится тот факт, что компилятор С# делает все Equals
, GetHashCode
и ToString
для вас, вы можете просто использовать что-то вроде ILSpy для захвата исходного кода. Таким образом:
class AreaInfo
{
public string Name { get; set; }
public int Total { get; set; }
public int All { get; set; }
public override bool Equals(object obj)
{
var ai = obj as AreaInfo;
if (object.ReferenceEquals(ai, null))
return false;
return Name == ai.Name && Total == ai.Total && All == ai.All;
}
public override int GetHashCode()
{
var hc = 0;
if (Name != null)
hc = Name.GetHashCode();
hc = unchecked((hc * 7) ^ Total);
hc = unchecked((hc * 21) ^ All);
return hc;
}
public override string ToString()
{
return string.Format("{{ Name = {0}, Total = {1}, All = {2} }}", Name, Total, All);
}
}
Исправьте словарь:
var areas = new Dictionary<string, AreaInfo>
{
{"Key1", new AreaInfo() {Name = "Name1", Today = 0, All = 0}},
{"Key2", new AreaInfo() {Name = "Name2", Today = 0, All = 0}},
...
};
И теперь все будет работать так, как вы ожидаете.
Чтобы получить свой словарь для правильного анонимного типа для его значения, сделайте следующее:
var areas=new[] {
new {Key="Key1", Value=new {name="Name1", today=0, all=0}},
new {Key="Key2", Value=new {name="Name2", today=0, all=0}},
}.ToDictionary(kv => kv.Key, kv => kv.Value);
Тогда ваш код будет работать так, как ожидалось:
foreach(var area in areas.Keys.ToArray()) {
var areaname=areas[area].name;
}
Детали анонимных типов не переносятся за рамки сборки, в которой они созданы, и не легко видимы за пределами метода, в котором они создаются. Вместо этого вы должны использовать вместо него явный тип или dynamic
если вы хотите использовать динамический подход,
† Здесь есть злой трюк, который я намеренно не упоминаю, потому что он злой.