edit Struct value in Unity C# - c#

I have created a dictionary named Teams and I use a struct to make hold an integer, a string and a boolean.
So if anyone joins a red team, the bool will be false to prevent other players from joining same team.
I tried to set the boolean to false but it failed.
public Dictionary <int , myCustomType> Teams = new Dictionary<int,myCustomType>();
private ExitGames.Client.Photon.Hashtable m_PlayerCustomPropeties = new ExitGames.Client.Photon.Hashtable();
private void addTeams()
{
myCustomType t=new myCustomType();
t.name="Yellow";
t.flag= true;
Teams.Add(1,t);
t.name="Red";
t.flag= true;
Teams.Add(2,t);
t.name="Blue";
t.flag= true;
Teams.Add(3,t);
t.name="Green";
t.flag= true;
Teams.Add(4,t);
Debug.Log("Teams created.");
}
public void getPlayers()
{
Debug.Log(Teams[1].flag);
Teams[1] = new myCustomType { flag = false };
}

Your type is defined as:
public struct myCustomType
{
public string name;
public bool flag;
}
And Teams is a Dictionary<int, myCustomType>. When you tried something like:
Teams[1].flag = false;
it failed because Teams[1] is just a value (the return value of the Dictionary<,> indexer getter).
Your type myCustomType is a mutable struct. The struct is returned by value, so it makes no sense to try to modify the returned copy of the value.
You will need:
var mct = Teams[1]; // 'mct' is a copy of the value from the 'Dictionary<,>'.
mct.flag = false; // You modify the copy which is allowed because 'mct' is a variable.
Teams[1] = mct; // You overwrite the old value with 'mct'.
Some people consider mutable structs evil.

This seems like an anti-pattern. Make your struct immutable (you may not want a struct for this anyway, especially if the team needs other functionality):
public struct myCustomType
{
public string Name { get; }
public myCustomType(string name)
{
this.Name = name;
}
}
Create a set of available teams, which you populate similarly to your addteams method:
public Dictionary<string, myCustomType> AvailableTeams; //color, team
public void InitializeTeams()
{
AvailableTeams = new Dictionary<string, myCustomType>()
{
["Yellow"] = new myCustomType("Yellow"),
["Red"] = new myCustomType("Red"),
["Blue"] = new myCustomType("Blue"),
["Green"] = new myCustomType("Green")
};
}
When a player joins a team, remove that team from the available set, and add it to a set of ActiveTeams:
public Dictionary<int, myCustomType> ActiveTeams; //player #, team
public void JoinTeam(int playerNumber, string teamColor)
{
if (!AvailableTeams.TryGetValue(teamColor, out myCustomType team)
// handle team already taken.
ActiveTeams.Add(playerNumber, team);
AvailableTeams.Remove(teamColor);
}

Related

C# - Is it possible to tell whether a property has been initialized with its default value or not initialized at all?

Say we work with this class:
public class UsefulClass
{
public string A { get; set; }
public string B { get; set; }
public int? C { get; set; }
public int? D { get; set; }
public decimal E { get; set; }
public decimal F { get; set; }
}
Let's consider the following instance:
UsefulClass z_objUsefulInstance = new UsefulClass()
{
A = null,
C = null,
E = 0
};
At this point, z_objUsefulInstance.A and C are null, E is 0, B, D and F have not been initialized.
Is there a way to tell, automatically, which properties of z_objUsefulInstance haven't been initialized and which ones have been initialized with null or 0?
EDIT: by popular demand, why I need this: to emulate a system of database access akin to EntityFramework. Right now all properties are a specific generic type, so it's rather easy to know which is null and which is Generic<T>.HasNullValue == true. But that generic type causes various issues and now we'd like to get rid of it, particularly as we have grown more conversant with Expressions.
Is there a way to tell, automatically, which properties of z_objUsefulInstance haven't been initialized and which ones have been initialized with null or 0?
You can't really know in ways that you can easily inspect at runtime what properties have been set unless you intercept the property setter and set some sort of flag. from a first-principals perspective that would resemble something like this:
public class UsefulClass
{
public string A { get => _a; set { _a = value; A_Set = true; } }
private string _a;
private bool A_Set = false;
public string B { get => _b; set { _b = value; B_Set = true; } }
private string _b;
private bool B_Set = false;
public int? C { get => _c; set { _c = value; C_Set = true; } }
private string _c;
private bool C_Set = false;
public int? D { get => _d; set { _d = value; D_Set = true; } }
private string _d;
private bool D_Set = false;
public decimal E { get => _e; set { _e = value; E_Set = true; } }
private string _e;
private bool E_Set = false;
public decimal F { get => _f; set { _f = value; F_Set = true; } }
private string _f;
private bool F_Set = false;
}
It is pretty verbose, but you can see here how we are not comparing the value at all, we can determine definitively if each property has been set, thought not specifically during the initialization of the instance, this simple code only tracks if each property was set at all.
So after your init, we can inspect these new flags:
UsefulClass z_objUsefulInstance = new UsefulClass()
{
A = null,
C = null,
E = 0
};
Console.WriteLine(z.C_Set); // True
Console.WriteLine(z.D_Set); // False
We can simplify this with a dictionary for the backing store and helper methods to get and set the property values, we can even encapsulate that logic in a base class to make this easier to consume:
public class UsefulClass : PropertyTracker
{
public string A { get => GetProperty<string>(); set => SetProperty(value); }
public string B { get => GetProperty<string>(); set => SetProperty(value); }
public int? C { get => GetProperty<int?>(); set => SetProperty(value); }
public int? D { get => GetProperty<int?>(); set => SetProperty(value); }
public decimal E { get => GetProperty<decimal>(); set => SetProperty(value); }
public decimal F { get => GetProperty<decimal>(); set => SetProperty(value); }
}
public abstract class PropertyTracker
{
private Dictionary<string, object> _values = new Dictionary<string, object>();
protected void SetProperty<T>(T value, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
{
_values[propertyName] = value;
}
protected T GetProperty<T>([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
{
if (!_values.ContainsKey(propertyName))
return default;
return (T)_values[propertyName];
}
public bool IsSet(string propertyName)
{
return _values.ContainsKey(propertyName);
}
}
See we still have the concept of a backing store, it's just not a field anymore. The inspection code is a bit different too:
UsefulClass z_objUsefulInstance = new UsefulClass()
{
A = null,
C = null,
E = 0
};
Console.WriteLine(z.IsSet(nameof(UsefulClass.C)); // True
Console.WriteLine(z.IsSet(nameof(UsefulClass.D)); // False
There are all sorts of techniques you can use to scaffold this or similar code out across your classes, this is just an example implementation. You could even write a generic wrapper that uses reflection to do the same thing. In my solutions I tend to use T4 templates to generate what are effectively View Model classes. My main argument was that I could generate some verbose code and take a hit at compile-time instead of a performance hit at runtime with a reflection based implementation.
If your ViewModel classes inherit from your model class, then you can get close to an apparently automatic implementation that is more compatible with the rest of your runtime, but that would require your properties be declared as virtual to enable the inheriting class to override the implementation.
If you end up going down this route, consider adding value to your classes by implementing INotifyPropertyChanged, or perhaps IChangeTracking or IRevertibleChangeTracking while you're there.
UsefulClass z_objUsefulInstance = new UsefulClass() {
A = null
C = null,
E = 0
};
At this point, z_objUsefulInstance.A and C are null, E is 0,
B, D and F have not been initialized.
No that's not quite right.
From "14.11.4 Constructor Execution" in the C#7 language spec
Variable initializers are transformed into assignment statements, and these assignment statements are executed before the invocation of the base class instance constructor.
So before your instance constructor in the above example is started executing, the properties are assigned
A = default(string); // null
B = default(string); // null
C = default(int?); // null
D = default(int?); // null
E = default(decimal); // 0.0m
F = default(decimal); // 0.0m
(Not quite accurate, but close enough for this answer)
Then your instance constructor is run (in this example, the default provided by the compiler), then your property assignments are made
A = null,
C = null,
E = 0
. There's no difference between E = 0 and E = default(decimal), nor is there a difference between null and null (default(string)).
If you need to tell whether a property was set or not you will have to provide a backing field, or otherwise control access to the property.
If you want to read more about constructor details, a friendlier summary than the language spec can be found at https://jonskeet.uk/csharp/constructors.html .

Returning a reference of a struct instead of a copy on C# 3.0?

I have this code:
using System;
using System.Collections.Generic;
using UnityEngine;
public interface HaveId
{
int id { get; }
}
public struct BusinessData : HaveId
{
// business type data
public int graphic_asset_id;
public string name;
public int id { get; set; }
}
public class LookupHelper<T> where T: HaveId
{
private T[] _list;
public T[] list
{
get { return _list; }
set { _list = value; _mapToDictionary(); }
}
private Dictionary<int, int> idxById = new Dictionary<int, int>();
public LookupHelper(){}
private void _mapToDictionary()
{
if(idxById.Count > 0) idxById = new Dictionary<int, int>();
for(var z =0 ; z < list.Length; ++z)
{
idxById[list[z].id] = z;
}
}
public bool IsIdExists(int id)
{
return idxById.ContainsKey(id);
}
public T ById(int id) // is this a reference?
{
var idx = idxById[id];
if (idx >= list.Length) throw new Exception(
String.Format("Invalid Index: {0} >= {1} on {2}",idx.ToString(),list.Length.ToString(), typeof(T).Name)
);
return list[idx];
}
}
And the test code:
LookupHelper<BusinessData> bd = new LookupHelper<BusinessData>();
bd.list = new BusinessData[]
{
new BusinessData{id = 1, name = "test"},
new BusinessData{id = 2, name = "test2"},
};
bd.ById(1).name = "foo";
This give an error: "Cannot modify struct member when accessed struct is not classified as a variable"
How can I change the value of first BusinessData and keep the array still allocated on a contiguous memory (array of struct, needed for cache locality)?
This should be a simple matter of splitting it up into a few lines. Extract the object to get a copy, modify the copy, then overwrite it in the array:
BusinessData bsd = bd.ById(1);
bsd.name = "foo";
bd.SetById(1, bsd);
Of course, you'll need to write that SetById method to reinsert things into the array:
public void SetById(int id, T obj)
{
Int32 idx = idxById[id];
list[idx] = obj;
}
As you know C# borrowed something’s from C and Java. But not everything.
In C, you can create a place for struct on the stack or the heap. On the heap, I can then pass a pointer around and change the content. Very powerful.
But C# emphasizes ease of memory management via garbage collection. To make it easy, C# has the concept of boxing value types into System.Object. Additional details, can be found on Microsoft C# Programming Guide on Boxing and unboxing.
So when you access the value type in your list, you have to explicitly unbox the value. Therefore it’s a copy of the item in the list. You can do what #Nyerguds suggested.
But to make life easy, why not turn your BusinessData into a class?

Why is my game serializing this class?

So I'm making a game, and it saves users' progress on the computer in a binary file. The User class stores a few things:
Integers for stat values (Serializable)
Strings for the Username and the skin assets
Lists of both the Achievement class and the InventoryItem class, which I have created myself.
Here are the User fields:
public string Username = "";
// ID is used for local identification, as usernames can be changed.
public int ID;
public int Coins = 0;
public List<Achievement> AchievementsCompleted = new List<Achievement>();
public List<InventoryItem> Inventory = new List<InventoryItem>();
public List<string> Skins = new List<string>();
public string CurrentSkinAsset { get; set; }
The Achievement class stores ints, bools, and strings, which are all serializable. The InventoryItem class stores its name (a string) and an InventoryAction, which is a delegate that is called when the item is used.
These are the Achievement class's fields:
public int ID = 0;
public string Name = "";
public bool Earned = false;
public string Description = "";
public string Image;
public AchievmentDifficulty Difficulty;
public int CoinsOnCompletion = 0;
public AchievementMethod OnCompletion;
public AchievementCriteria CompletionCriteria;
public bool Completed = false;
And here are the fields for the InventoryItem class:
InventoryAction actionWhenUsed;
public string Name;
public string AssetName;
The source of the InventoryAction variables are in my XNAGame class. What I mean by this is that the XNAGame class has a method called "UseSword()" or whatever, which it passes into the InventoryItem class. Previously, the methods were stored in the Game1 class, but the Game class, which Game1 inherits from, is not serializable, and there's no way for me to control that. This is why I have an XNAGame class.
I get an error when trying to serialize: "The 'SpriteFont' class is not marked as serializable", or something like that. Well, there is a SpriteFont object in my XNAGame class, and some quick tests showed that this is the source of the issue. Well, I have no control over whether or not the SpriteFont class is Serializable.
Why is the game doing this? Why must all the fields in the XNAGame class be serializable, when all I need is a few methods?
Keep in mind when answering that I'm 13, and may not understand all the terms you're using. If you need any code samples, I'll be glad to provide them for you. Thanks in advance!
EDIT: One solution I have thought of is to store the InventoryAction delegates in a Dictionary, except that this will be a pain and isn't very good programming practice. If this is the only way, I'll accept it, though (Honestly at this point I think this is the best solution).
EDIT 2: Here's the code for the User.Serialize method (I know what I'm doing in inefficient, and I should use a database, blah, blah, blah. I'm fine with what I'm doing now, so bear with me.):
FileStream fileStream = null;
List<User> users;
BinaryFormatter binaryFormatter = new BinaryFormatter();
try
{
if (File.Exists(FILE_PATH) && !IsFileLocked(FILE_PATH))
{
fileStream = File.Open(FILE_PATH, FileMode.Open);
users = (List<User>)binaryFormatter.Deserialize(fileStream);
}
else
{
fileStream = File.Create(FILE_PATH);
users = new List<User>();
}
for (int i = 0; i < users.Count; i++)
{
if (users[i].ID == this.ID)
{
users.Remove(users[i]);
}
}
foreach (Achievement a in AchievementsCompleted)
{
if (a.CompletionCriteria != null)
{
a.CompletionCriteria = null;
}
if (a.OnCompletion != null)
{
a.OnCompletion = null;
}
}
users.Add(this);
fileStream.Position = 0;
binaryFormatter.Serialize(fileStream, users);
You cannot serialize a SpriteFont by design, actually this is possible (.XNB file) but it hasn't been made public.
Solution:
Strip it off your serialized class.
Alternatives:
If for some reasons you must serialize some font, the first thing that comes to my mind would be to roll-out your own font system such as BMFont but that's a daunting task since you'll have to use it everywhere else where you might already do ...
Generate a pre-defined amount of fonts (i.e. Arial/Times/Courier at size 10/11/12 etc ...) using XNA Content app (can't recall its exact name); then store this user preference as two strings. With a string.Format(...) you should be able to load the right font back quite easily.
Alternative 2 is certainly the easiest and won't take more than a few minutes to roll-out.
EDIT
Basically, instead of saving a delegate I do the following:
inventory items have their own type
each type name is de/serialized accordingly
their logic does not happen in the main game class anymore
you don't have to manually match item type / action method
So while you'll end up with more classes, you have concerns separated and you can keep your main loop clean and relatively generic.
Code:
public static class Demo
{
public static void DemoCode()
{
// create new profile
var profile = new UserProfile
{
Name = "Bill",
Gold = 1000000,
Achievements = new List<Achievement>(new[]
{
Achievement.Warrior
}),
Inventory = new Inventory(new[]
{
new FireSpell()
})
};
// save it
using (var stream = File.Create("profile.bin"))
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, profile);
}
// load it
using (var stream = File.OpenRead("profile.bin"))
{
var formatter = new BinaryFormatter();
var deserialize = formatter.Deserialize(stream);
var userProfile = (UserProfile) deserialize;
// set everything on fire :)
var fireSpell = userProfile.Inventory.Items.OfType<FireSpell>().FirstOrDefault();
if (fireSpell != null) fireSpell.Execute("whatever");
}
}
}
[Serializable]
public sealed class UserProfile
{
public string Name { get; set; }
public int Gold { get; set; }
public List<Achievement> Achievements { get; set; }
public Inventory Inventory { get; set; }
}
public enum Achievement
{
Warrior
}
[Serializable]
public sealed class Inventory : ISerializable
{
public Inventory() // for serialization
{
}
public Inventory(SerializationInfo info, StreamingContext context) // for serialization
{
var value = (string) info.GetValue("Items", typeof(string));
var strings = value.Split(';');
var items = strings.Select(s =>
{
var type = Type.GetType(s);
if (type == null) throw new ArgumentNullException(nameof(type));
var instance = Activator.CreateInstance(type);
var item = instance as InventoryItem;
return item;
}).ToArray();
Items = new List<InventoryItem>(items);
}
public Inventory(IEnumerable<InventoryItem> items)
{
if (items == null) throw new ArgumentNullException(nameof(items));
Items = new List<InventoryItem>(items);
}
public List<InventoryItem> Items { get; }
#region ISerializable Members
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
var strings = Items.Select(s => s.GetType().AssemblyQualifiedName).ToArray();
var value = string.Join(";", strings);
info.AddValue("Items", value);
}
#endregion
}
public abstract class InventoryItem
{
public abstract void Execute(params object[] objects);
}
public abstract class Spell : InventoryItem
{
}
public sealed class FireSpell : Spell
{
public override void Execute(params object[] objects)
{
// using 'params object[]' a simple and generic way to pass things if any, i.e.
// var world = objects[0];
// var strength = objects[1];
// now do something with these !
}
}
Okay, so I figured it out.
The best solution was to use a Dictionary in the XNAGame class, which stores two things: an ItemType (an enumeration), and an InventoryAction. Basically, when I use an item, I check it's type and then look up it's method. Thanks to everyone who tried, and I'm sorry if the question was confusing.

Looping to Create and Add New Objects to ArrayList

Edit to save you from reading through this whole post
tldr: an object's fields should not be static unless you want all instances of that object to have the same value for that field
I'm trying to create and populate an ArrayList of Blog objects. I do know the generic way do this:
create ArrayList of Blogs
loop (some condition)
create new Blog
add this Blog to AL
However, when I attempt to do so within the while(datareader.read()) loop, all of the elements in the ArrayList are exactly the same Blog. Specifically, I end up with an ArrayList filled with multiple pointers to the very last Blog object from the database table. Here is my code:
public static ArrayList AllBlogs()
{
SqlDataReader dr = anonPage.ExecuteReader("SELECT * FROM Kristina_Blogs");
ArrayList allBlogs = new ArrayList();
if (dr.HasRows)
{
while (dr.Read())
{
Blog b = new Blog();
//grab a row from Kristina_Blogs and assign those attributes to b
b.setTitle(dr["title"].ToString());
b.setMessage(dr["message"].ToString());
b.setId(dr["id"]);
allBlogs.Add(b);
}
}
dr.Close();
return allBlogs;
}
As I said before, the result of this is an ArrayList filled with pointers to the very last blog from the Kristina_Blogs table. I imagine the ArrayList allBlogs looks like [b, b, b, ... b] and therefore they ALL get updated when I say b.setTitle() etc. But how can this be the case if I am creating a NEW Blog object at the beginning of each iteration?
Here is some extra info that you don't have to read but it might clear up some confusion about the structure of the problem:
Blog object has id, title, and message fields and their respective getter/setters
Kristina_Blogs is a table representing these blogs with columns for id, title, message
The suggestions say to include a tag for my DB engine but I can't find a tag for it: Microsoft SQL Server Management Studio
This code works perfectly when I use an ArrayList of Strings instead of Blogs
Edit: Including the code from Blog class
public class Blog
{
public App myApp;
public static string Title;
public static string Message;
public static int Id;
//constructors
public Blog() { }
public Blog(App App) { this.myApp = App; }
//all getters and setters look like this
public string getTitle() { return Title; }
public void setTitle(string t) { Title = t; }
}
The main problem you have, as I mentioned in comments is your member variables are static, so when you set the value, they change in all instances. you should change your code this way:
public class Blog
{
public int Id { get; set; }
public string Title { get; set; }
public string Message { get; set; }
}
And fill your list this way, don't forget to add using System.Linq;:
var result = new List<Blog>();
var connection = #"your connection string";
var command = "SELECT * FROM Kristina_Blogs";
var adapter = new System.Data.SqlClient.SqlDataAdapter(command, connection);
var dataTable = new DataTable();
//Get data
adapter.Fill(dataTable);
dataTable.Rows.Cast<DataRow>().ToList()
.ForEach(row =>
{
var b = new Blog();
b.Id = row.Field<int>("Id");
b.Title = row.Field<string>("Title");
b.Message = row.Field<string>("Message");
result.Add(b);
});
return result;
Note:
When you create a member static, it is shared between all instances of that calss.
In C# you can use property to get or set values, you don't need to setX or setY, when you get the value of a property, the get code of that property will execute and when you assign a value to a property the set part of it will execute. you can define properties this way:
Property:
private int id;
public int Id
{
get
{
return id;
}
set
{
id = value;
}
}
or more simple:
public int Id { get; set; }
All of the fields in your Blog class are static, meaning they're shared between all object instances. You want them to be instance field (meaning not static) so that each object has its own copy of each of those values.
Remove the static attributes from your class:
public class Blog
{
public App myApp;
public String Title;
public String Message;
public int Id;
//constructors
public Blog() { }
public Blog(App App) { this.myApp = App; }
//all getters and setters look like this
public String getTitle() { return Title; }
public String getMessage() { return Message; }
public void setTitle(String t) { Title = t; }
public void setMessage(String m) { Message = m; }
}
When you use static variables, all instances of an object will contain the same values in those variables. By removing the static keyword, you are allowing different instances of the object to hold different values.
Now, every time you create a blog object, that object's Title and Message etc, will contain its own information.
I would make a quick method to prevent null value from throwing error
public static string GetSafeString(SqlDataReader reader, int index)
{
if (!reader.IsDBNull(index))
return reader.GetString(index);
else
return string.Empty;
}
Replace this code:
while (dr.Read())
{
Blog b = new Blog();
//grab a row from Kristina_Blogs and assign those attributes to b
b.setTitle(dr["title"].ToString());
b.setMessage(dr["message"].ToString());
b.setId(dr["id"]);
allBlogs.Add(b);
}
With This Code:
while (dr.Read())
{
Blog b = new Blog();
//grab a row from Kristina_Blogs and assign those attributes to b
b.setId(dr.GetInt32(0));
b.setTitle(GetSafeString(dr, 1);
b.setMessage(GetSafeString(dr, 2);
allBlogs.Add(b);
}
Where the number is the index of field in the record and assuming "id" is an integer. Also consider moving creation of "Blog" object outside of loop and just change values.

Better way to manage Session data

I need to persist in Session some data.
I wrote many properties like that:
public List<string> FillOrder
{
get { return Session[SessionKeys.QueryFillOrder] as List<string> ?? new List<string>(); }
set { Session[SessionKeys.QueryFillOrder] = value; }
}
When I have to consume this data I have to write code like that:
List<string> fillOrder = FillOrder;
fillOrder.Add(accordion.ID);
FillOrder = fillOrder;
that seems to me so ugly, because I would prefer to do that:
FillOrder.Add(accordion.ID);
but this way my value would not be saved back in Session.
Can you think of any better way to achieve the same result?
Thank you very much!
I always use a wrapper class around the ASP.NET session to simplify access to session variables:
public class MySession
{
// private constructor
private MySession()
{
FillOrder = new List<string>();
}
// Gets the current session.
public static MySession Current
{
get
{
var session = (MySession)HttpContext.Current.Session["__MySession__"];
if (session == null)
{
session = new MySession();
HttpContext.Current.Session["__MySession__"] = session;
}
return session;
}
}
// **** add your session properties here, e.g like this:
public List<string> FillOrder {get; set; }
public string Property1 { get; set; }
public DateTime MyDate { get; set; }
public int LoginId { get; set; }
}
This class stores one instance of itself in the ASP.NET session and allows you to access your session properties in a type-safe way from any class, e.g like this:
MySession.Current.FillOrder.Add(accordion.ID);
int loginId = MySession.Current.LoginId;
string property1 = MySession.Current.Property1;
MySession.Current.Property1 = newValue;
DateTime myDate = MySession.Current.MyDate;
MySession.Current.MyDate = DateTime.Now;
This approach has several advantages:
you can initialize your session variables in the constructor (i.e. new List<string>)
it saves you from a lot of type-casting
you don't have to use hard-coded session keys throughout your application (e.g. Session["loginId"]
you can document your session items by adding XML doc comments on the properties of MySession
You can use an extension method as well, but I do think the example by M4N might be better:
EDIT made it a generic type
public static class Extensions
{
public static void AddWithSession<T>(this List<T> list, T value, string key)
{
list.Add(value);
HttpContext.Current.Session[key] = list;
}
}
str.AddWithSession(accordion.ID,SessionKeys.QueryFillOrder);
You could write an own class that implements ICollection or IList, there you would implement Add as Session[...] = ...
Using a single class for all Session variables as suggested by #M4N is a good idea, though it risks becoming a "God" class (in which case you could partition into several classes implemented in this way).
However you could just change your property implemetation as follows:
public List<string> FillOrder
{
get
{
List<string> result = Session[SessionKeys.QueryFillOrder] as List<string>;
if (result == null)
{
result = new List<string>();
Session[SessionKeys.QueryFillOrder] = result;
}
return result;
}
set { Session[SessionKeys.QueryFillOrder] = value; }
}
In this example, you probably don't want a setter.

Categories

Resources