Why Are the Properties of Anonymous Types in C# Read-Only

Non-read only alternative to anonymous types

No, you'll have to create your own class or struct to do this (preferrably a class if you want it to be mutable - mutable structs are horrible).

If you don't care about Equals/ToString/GetHashCode implementations, that's pretty easy:

public class MyClass {
public bool Foo { get; set; }
public bool Bar { get; set; }
}

(I'd still use properties rather than fields, for various reasons.)

Personally I usually find myself wanting an immutable type which I can pass between methods etc - I want a named version of the existing anonymous type feature...

Why are the properties of anonymous types in C# read-only?

Interesting article on that here. From there ...

... [B]y ensuring that the members do
not change, we ensure that the hash is
constant for the lifetime of the
object.This allows anonymous types to
be used with collections like
hashtables, without actually losing
them when the members are modified.
There are a lot of benefits of
immutabilty in that, it drastically
simplifies the code that uses the
object since they can only be assigned
values when created and then just used
(think threading)

How does C# set a read-only property on anonymous object initialization

The object initializer for anonymous types doesn't behave like a normal object initializer. i.e. it doesn't set the properties directly. It gets translated into a call to the constructor, which can change readonly fields.

C# Anonymous types cannot be assigned to -- it is read only

Anonymous types in C# are immutable and hence do not have property setter methods. You'll need to create a new anonmyous type with the values

obj = new { Name = "asdasd", Price = 11.00 };

Why Getter in Anonymous Types?

Because properties of anonymous types are readonly after construction. You cannot change them once the object has been created.

They can achieve this using a get only property, but not with a public field (you can always change a field).


EDIT: I've looked around but couldn't find an obvious reason as to why they didn't go with public read-only fields. However, my best guess is: so that you can have properties.

If they had exposed public fields, and didn't have any properties, inevitably, anonymous types would be unusable by things that look for public properties, e.g. WPF binding. So having properties with private readonly backing fields probably was the safer choice.

Get read/write properties of Anonymous Type

Anonymous types generated from C# are always immutable, so the set of writable properties is empty. In VB it's optional: each property defaults to being mutable, but if you prefix it with Key it's immutable; only properties declared using Key count for equality and hash code generation. Personally I prefer C#'s approach.

CanWrite isn't always returned as true for properties in non-anonymous types - only for writable ones. Properties can be read-only, write-only, or read-write. For example:

public class Test
{
// CanWrite will return false. CanRead will return true.
public int ReadOnly { get { return 10; } }

// CanWrite will return true. CanRead will return false.
public int WriteOnly { set {} }

// CanWrite will return true. CanRead will return true.
public int ReadWrite { get { return 10; } set {} }
}

Setting a read-only property with anonymous type

AddSomeNodes is not creating an instance of List<TreeNode> because that syntax is a collection initializer (therefore it is not assigning to Nodes meaning it doesn't break the readonly contract), the compiler actually translates the collection initializer into calls to .Add.

The AddSomeOtherNodes call actually tries to re-assign the value, but it is readonly. This is also the object initializer syntax, which translates into simple property calls. This property does not have a setter, so that call generates a compiler error. Attempting to add a setter that sets the readonly value will generate another compiler error because it is marked readonly.

From MSDN:

By using a collection initializer you do not have to specify multiple
calls to the Add method of the class in your source code; the compiler
adds the calls.

Also, just to clarify, there are no anonymous types in play in your code - it is all initializer syntax.



Unrelated to your question, but in the same area.

Interestingly, the Nodes = { new TreeNode() } syntax doesn't work with a local member, it only seems to work when it is nested inside an object initializer or during object assignment:

List<int> numbers = { 1, 2, 3, 4 }; // This isn't valid.
List<int> numbers = new List<int> { 1, 2, 3, 4 }; // Valid.

// This is valid, but will NullReferenceException on Numbers
// if NumberContainer doesn't "new" the list internally.
var container = new NumberContainer()
{
Numbers = { 1, 2, 3, 4 }
};

The MSDN documentation doesn't seem to have any clarification on this.

How to set value for property of an anonymous object?

Anonymous type properties are read only and they cannot be set.

Anonymous types provide a convenient way to encapsulate a set of
read-only properties
into a single object without having to explicitly
define a type first. The type name is generated by the compiler and is
not available at the source code level. The type of each property is
inferred by the compiler.

Anonymous Types (C# Programming Guide)

LINQ - Assign a Value to Anonymous Type's Read Only Property

Instead of trying to change the value after creating the list, just set the right value while creating the list.

var list = from c in db.Mesai
join s in db.MesaiTip on c.mesaiTipID equals s.ID
where c.iseAlimID == iseAlimID
select new
{
tarih = c.mesaiTarih,
mesaiTip = s.ad,
mesaiBaslangic = c.mesaiBaslangic,
mesaiBitis = c.mesaiBitis,
sure = c.sure,
condition = c.onaylandiMi,
status = c.onaylandiMi != null ? c.status : "Not Confirmed"
};

Also, if you could change the property, your problem would be executing the query twice: first in the foreach-loop, and then again by calling list.ToList() (which would create new instances of the anonymous type).



Related Topics



Leave a reply



Submit