Вариант со вложенным классом работает:
namespace TestApp
{
class Program
{
static void Main(string[] args)
{
Item.ItemManager manager = new Item.ItemManager();
//Item i = new Item("name", 0); //'TestApp.Item' does not contain a constructor that takes 2 arguments
Item i1 = manager.CreateItem("item", 1);
Console.WriteLine(i1); //Output: "Item id=1, name=item"
//i1.Id = 2; //The property or indexer 'TestApp.Item.Id' cannot be used in this context because the set accessor is inaccessible
//i1.Name = "item1"; //The property or indexer 'TestApp.Item.Name' cannot be used in this context because the set accessor is inaccessible
manager.ChangeId(i1, 2);
manager.ChangeName(i1, "item1");
Console.WriteLine(i1); //Output: "Item id=2, name=item1"
Console.ReadLine();
}
}
public class Item
{
public string Name { get; private set; }
public int Id { get; private set; }
private Item(string _name, int _id)
{
Name = _name;
Id = _id;
}
public override string ToString()
{
return string.Format("Item id={0}, name={1}", Id, Name);
}
public class ItemManager
{
public Item CreateItem(string name, int id)
{
return new Item(name, id);
}
public void ChangeName(Item item, string newName)
{
item.Name = newName;
}
public void ChangeId(Item item, int newId)
{
item.Id = newId;
}
}
}
}
И если все же решите использовать изменяемые структуры, будьте аккуратны с ними.