Read HttpRuntime.Cache item as read-only - c#

I am using a HttpRuntime.Cache to store a list of objects that will be accessing frequently across sessions.
I use the following line of code to get the item from the cache:
List<chartData_Type> _chartData =
(List<chartData_Type>)HttpRuntime.Cache.Get("rollingMonth");
But, unfortunately when I update the _chartData, it updates the cached item too.
How can I simply get a copy of the cached item?

That is the way which .NET works because Cache just reference to the pointer of List. Don't know whether you chartData_Type is value type or reference type.
If value type, it is easy to use:
List<chartData_Type> list = new List<chartData_Type>(_chartData);
But if reference type, it comes to complicated, you need to implement DeepCopy method for your class, then do DeepCopy for each object in list.
DeepClone method:
public static class CloneHelper
{
public static T DeepClone<T>(T obj)
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
return (T) formatter.Deserialize(ms);
}
}
}
In order to use this method, class chartData_Type must be marked [Serializable]:
[Serializable]
class chartData_Type
{}
So, you can do deep clone manually:
var cloneChartData = _chartData.Select(d =>
CloneHelper.DeepClone<chartData_Type>(d))
.ToList();

Use:
List<chartData_Type> list = new List<chartData_Type>(_chartData);
It will copy all items from _chartData to list.

List is a reference type and _chartData holds the address of the original object stored in the cache. That is why when you update _chartData, it updates the cached object too. If you want a separate object then clone the cached object. See below reference
http://www.codeproject.com/Articles/33364/ASP-NET-Runtime-Cache-Clone-Objects-to-Preserve-Ca
http://www.codeproject.com/Articles/45168/ASP-NET-Runtime-Cache-Clone-Objects-to-Preserve-Ca

Related

List<String> ByRef

I'm wondering how one can prove what the .Net framework is doing behind the scenes.
I have a method that accepts a parameter of a List<String> originalParameterList.
In my method I have another List<String> newListObj if I do the following:
List<String> newListObj = originalParameterList
newListObj.Add(value);
newListObj.Add(value1);
newListObj.Add(value2);
The count of the originalParameterList grows (+3).
If I do this:
List<String> newListObj = new List<String>(originalParamterList);
newListObj.Add(value);
newListObj.Add(value1);
newListObj.Add(value2);
The count of the originalParameterList stays the sames (+0).
I also found that this code behaves the same:
List<String> newListObj = new List<String>(originalParamterList.ToArray());
newListObj.Add(value);
newListObj.Add(value1);
newListObj.Add(value2);
The count of the originalParameterList stays the sames (+0).
My question is, is there a way to see what the .Net Framework is doing behind the scenes in a definitive way?
You can load your assembly into ILDASM and(when loaded),find your method and double-click it,
it will show the cil code of that method.Just type "IL" in windows start menu in the search.
Alternatively you can you can use these following ways to also create a new independent list
private void GetList(List<string> lst)
{
List<string> NewList = lst.Cast<string>().ToList();
NewList.Add("6");
//not same values.
//or....
List<string> NewList = lst.ConvertAll(s => s);
NewList.Add("6");
//again different values
}
Normally, the documentation should give enough information to use the API.
In your specific example, the documentation for public List(IEnumerable<T> collection) says (emphasis mine):
Initializes a new instance of the List class that contains elements
copied from the specified collection and has sufficient capacity to
accommodate the number of elements copied.
For the reference here is the source code for the constructor:
public List (IEnumerable <T> collection)
{
if (collection == null)
throw new ArgumentNullException ("collection");
// initialize to needed size (if determinable)
ICollection <T> c = collection as ICollection <T>;
if (c == null) {
_items = EmptyArray<T>.Value;;
AddEnumerable (collection);
} else {
_size = c.Count;
_items = new T [Math.Max (_size, DefaultCapacity)];
c.CopyTo (_items, 0);
}
}
void AddEnumerable (IEnumerable <T> enumerable)
{
foreach (T t in enumerable)
{
Add (t);
}
}
The simplest way to do it is simply go to MSDN
http://msdn.microsoft.com/en-us/library/fkbw11z0.aspx
It says that
Initializes a new instance of the List class that contains elements copied from the specified collection and has sufficient capacity to accommodate the number of elements copied.
so internally it`s simply add all elements of passed IEnumerable into new list. It also says that
this is a O(n) operation
which means that no optimizations assumed.
That's because the frist case you referenced the original list (since it is a reference type), and you modified it's collection via newListObj. The second and third case you copied the original objects' collection via List constructor List Class, and you modified the new collection, which is not take any effect to the original.
As others already said, there are various tools that let you examine the source code of the .NET framework. I personally prefer dotPeek from JetBrains, which is free.
In the specific case that you have mentioned, I think when you pass a list into the constructor of another list, that list is copied. If you just assign one variable to another, those variables are then simply referring to the same list.
You can either
read the documentation over at MSDN
decompile the resulting MSIL-code, for instance using Telerik's free JustDecompile
or step through the .NET Framework code using the debugger.
This is the code from List constrcutor:
public List(IEnumerable<T> collection)
{
if (collection == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.collection);
}
ICollection<T> collection2 = collection as ICollection<T>;
if (collection2 != null)
{
int count = collection2.Count;
this._items = new T[count];
collection2.CopyTo(this._items, 0);
this._size = count;
return;
}
this._size = 0;
this._items = new T[4];
using (IEnumerator<T> enumerator = collection.GetEnumerator())
{
while (enumerator.MoveNext())
{
this.Add(enumerator.Current);
}
}
}
As you can see when you calls costructor which takes IEnumerable it copies all data to itself.

How to assign List<T> without it being a reference to the original List<T>?

For example
List<string> name_list1 = new List<string>();
List<string> name_list2 = new List<string>();
later in the code:
name_list1.Add("McDonald");
name_list1.Add("Harveys");
name_list1.Add("Wendys");
name_list2 = name_list1; // I make a copy of namelist1 to namelist2
So, from this point I would like to keep adding element or making changes in name_list2 without affecting name_list1. How do I do that?
name_list2 = new List<string>(name_list1);
This will clone the list.
Edit: This solution only works for primitive types. For objects, see other responses below.
Another Options is : Deep Cloning
public static T DeepCopy<T>(T item)
{
BinaryFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
formatter.Serialize(stream, item);
stream.Seek(0, SeekOrigin.Begin);
T result = (T)formatter.Deserialize(stream);
stream.Close();
return result;
}
so,
you can use :
name_list2 = DeepCopy<List<string>>(name_list1);
OR:
name_list2 = DeepCopy(name_list1);
will also work.
For Primitive Types you can do this:
List<string> CopyList = new List<string>(OriginalList);
For non-primitve/user-difined types you can do this:
List<Person> CopyList = new List<Person>();
foreach(var item in OriginalList)
{
CopyList.Add(new Person {
Name = item.Name,
Address = item.Address
});
}
name_list2 = new List<string>(name_list1); // Clone list into a different object
At this point, the two lists are different objects. You can add items to list2 without affecting list1
The problem is the assignment. Until the assignment name_list2 = name_list1;, you have two different List objects on the heap pointed to by the variables name_list1 and name_list2. You fill up name_list1, which is fine. But the assignment says, "make name_list2 point to the same object on the heap as name_list1." The List that name_list2 used to point to is no longer accessible and will be garbage collected. What you really want is to copy the contents of name_list1 into name_list2. You can do this with List.AddRange. Note that this will result in a "shallow" copy, which is fine for the example you cite, where the list contents are strings, but may not be what you want when the list members are more complex objects. It all depends on your needs.
Based on #Mrunal answer I created an extension method:
public static T Clone<T>(this T source)
{
// Don't serialize a null object, simply return the default for that object
if (source == null)
{
return default;
}
// initialize inner objects individually
// for example in default constructor some list property initialized with some values,
// but in 'source' these items are cleaned -
// without ObjectCreationHandling.Replace default constructor values will be added to result
var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace };
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source), deserializeSettings);
}
And you can call it like this:
L2 = L1.Select(x => x.Clone()).ToList();
I like linq for this...
If list elements are primitives or structures then...
L2 = L1.ToList()
If list elements are classes then...
L2 = L1.Select(x => x.Copy()).ToList();
Where Copy could simply be a shallow copy exposure of MemberWiseClone, or it could be some implementation of a deep copy.
I prefer Json converter method to serialize and deserialize, this way you don't have to mark the classes for serialization, especially you have numerous child classes.
https://www.newtonsoft.com/json/help/html/SerializingJSON.htm
Here is an alternative solution:
List<string> name_list1 = new List<string>();
List<string> name_list2 = new List<string>();
name_list1.Add("McDonald");
name_list1.Add("Harveys");
name_list1.Add("Wendys");
name_list2.AddRange(name_list1.ToArray());
The ToArray() method copies 'name_list1' to a new array, which we then add to name_list2 via the AddRange() method.
For primitive types:
List ClonedList = new list(OriginalList);
For non-primitive/User Defined types:
We need to perform a deep copy:
Deep Copy is used to make a complete deep copy of the internal reference types, for this we need to configure the object returned by MemberwiseClone().
Step1- In your class inherit from ICloneable:
public class MyClass:ICloneable
Step2- Implement method
public MyClass Clone()
{
MyClass MyClassObj =new MyClass();
MyClassObj.Property1 = this.Property1;
.
.
MyClassObj.Property_N = this.Property_N;
return MyClass;
}
Step3- now clone your List
List<MyClass> MyClassClone = new List<MyClass>();
for(i=0; i<Count; i++)
{
MyClassClone.Add(OriginalClaaObj[i].Clone());
}
This will make deep copy of each item of the object.
None of the above solutions worked for me when using lists of class objects.
This can be used for copying any object to another object with shared property names.
public static void ObjectToObject(object source, object destination)
{
// Purpose : Use reflection to set property values of objects that share the same property names.
Type s = source.GetType();
Type d = destination.GetType();
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
var objSourceProperties = s.GetProperties(flags);
var objDestinationProperties = d.GetProperties(flags);
var propertyNames = objSourceProperties
.Select(c => c.Name)
.ToList();
foreach (var properties in objDestinationProperties.Where(properties => propertyNames.Contains(properties.Name)))
{
try
{
PropertyInfo piSource = source.GetType().GetProperty(properties.Name);
properties.SetValue(destination, piSource.GetValue(source, null), null);
}
catch (Exception ex)
{
throw;
}
}
}
public static List<T> CopyList<T>(this List<T> lst)
{
List<T> lstCopy = new List<T>();
foreach (var item in lst)
{
var instanceOfT = Activator.CreateInstance<T>();
ObjectToObject(item, instanceOfT);
lstCopy.Add(instanceOfT);
}
return lstCopy;
}
For lists use this:
list2 = list1.CopyList();
If both the lists are of the same complex type then you can do something like below:-
SomeClass List2 = new List();
List1.ForEach(u => List2.Add(u));
What I am doing is to loop through each element of List1 and keep adding it to List2.
I believe this is the shortest way to do it.
While it could be potential performance-threat solution, but it would copy the values property-by-property eloquently.
using Newstonsoft.Json;
ClassA classA = new ClassA();
ClassA classACopyWithoutReference = JsonConvert.DeserializeObject<ClassA>(JsonConvert.SerializeObject(classA));
this solution works For complex objects (Replace T with name of your Type):
list2 = list1.Concat(new List<T> { object }).ToList();
or:
list2 = list1.ToArray().Append(object).ToList()
You can clone the complex object by serialize and deserialize it, it will remove you object reference and create new object without reference
using Newstonsoft.Json;
List<string> name_list1 = new List<string>();
name_list1.Add("McDonald");
name_list1.Add("Harveys");
name_list1.Add("Wendys");
name_list2 = name_list1;
List<string> name_list2 = JsonConvert.DeserializeObject<List<string>>
(JsonConvert.SerializeObject(name_list1)); // Ii make a copy of namelist1 to namelist2
this is working for me using LINQ...
lst1= lst2.ToList();

c# by reference or by value

Let's say I have a list of objects and that I'm extracting and modifying an item from the list like this:
List<MyObject> TheListOfObjects = new List<MyObject>();
MyObject TheObject = new MyObject();
TheListOfObjects = //some json deserialization result
TheObject = (from o in TheListOfObject
where o.ID == SomeParameter
select o).SingleOrDefault();
TheObject.SomeProperty = SomeValue;
When I write TheObject.SomeProperty = SomeValue; am I:
modifying the item in the list and in which case I'm done or
modifying a new item and I must replace the original item in the list with the item I just modified.
Depends.
If the list of objects is a list of class instances, then TheObject variable will hold a value that is a reference. This reference will also still exist within the list. Modifications of the object at that reference will be visible in both. Important caveat: Writing over the reference contained in the variable (ie., variable reassignment) would not persist to the list, nor would writing over the reference in the list persist to the variable.
If the list of objects is a list of struct instances, then TheObject simply contains the value, and mutations of that value are not visible inside the list.
That depends on whether the MyObject is a class or a struct.
If it's a class, you're modifying the original object.
If it's a struct, you're modifying a copy.
Items in your list are held by reference, so you're modifying the same object - no need to try to copy it back into the list as it's already there.
You are modifying an item in the list. TheObject is a reference to an unique item in memory.
You can even create multiple lists, all lists will contain references to identical objects in memory.
There is something wrong with your code:
MyObject TheObject = new MyObject();
...
TheObject = (from o in TheListOfObject
where o.ID == SomeParameter
select o).SingleOrDefault();
You are first creating a new instance of the object, the affecting to TheObject a new value.
The = new MyObject(); part of your code is useless. Same for = new List<MyObject>();
You are modifying the item in the list as the call returns a reference to the item in the list, not a copy of it. Also, the object you create with
MyObject TheObject = new MyObject();
is just thrown away, as you change the reference to the newly selected item. You could omit that line and just do:
MyObject theObject = (from o in TheListOfObject
where o.ID == SomeParameter
select o).SingleOrDefault();
I assume that MyObject is a class, and not a struct, because we are mutating it with the operation, and mutable structs are evil

How to deep copy a matrix in C#?

I got a List<List<CustomClass>>, where CustomClass is a reference type.
I need to make a full deep copy of this matrix into a new one. Since I want a deep copy, each CustomClass object in the matrix has to be copied into the new matrix.
How would you do that in an efficient way?
For a CustomClass that implements ICloneable, this isn't very difficult:
var myList = new List<List<CustomClass>>();
//populate myList
var clonedList = new List<List<CustomClass>>();
//here's the beef
foreach(var sublist in myList)
{
var newSubList = new List<CustomClass>();
clonedList.Add(newSubList);
foreach(var item in sublist)
newSublist.Add((CustomClass)(item.Clone()));
}
You can make this work in a similar way with any "DeepCopy"-type method, if you feel you don't want to implement ICloneable (I would recommend using the built-in interface though).
One easier way to serialize the whole object and then deserialize it again, try this extension method:
public static T DeepClone<T>(this T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
USAGE
List<List<CustomClass>> foobar = GetListOfListOfCustomClass();
List<List<CustomClass>> deepClonedObject = foobar.DeepClone();
There are two possibilities:
Implement the ICloneable interface on your CustomClass, then you can clone your objects.
If the class can be serialized, serialize it to a memory stream and deserialize it from there. That will create a copy of it.
I would prefer to take the first alternative, because I think serializing / deserializing is slower than cloning via ICloneable.
Assuming you have a Copy method which can duplicate CustomClass objects:
var newMatrix = oldMatrix
.Select(subList => subList.Select(custom => Copy(custom)).ToList())
.ToList();

c# List<myObject> myList.copyTo() keeps a reference?

I've got a List and I used .copyTo() method. So it copies my List into one dimensional array.
So I loop this array and add each myObject to another List, then I'm changing things in this new List.
After this I'm showing the difference between the new values in my second List and the old values that are in my first List. But there is always no difference. So I'm thinking that the copyTo() method keeps a reference.
Are there other methods that doesn't keep a reference?
Yes. .CopyTo() performs a shallow copy, which means it copies the references. What you need is a deep copy, by cloning each object.
The best way is to make you myObject class implement IClonable
public class YourClass
{
public object Clone()
{
using (var ms = new MemoryStream())
{
var bf = new BinaryFormatter();
bf.Serialize(ms, this);
ms.Position = 0;
object obj = bf.Deserialize(ms);
ms.Close();
return obj;
}
}
}
Then you can cole .Clone() on each object and add that to a new List.
List<YourClass> originalItems = new List<YourClass>() { new YourClass() };
List<YourClass> newItemList = originalItems.Select(x => x.Clone() as YourClass).ToList();
If you've got a List of reference types, and you use the the CopyTo method to copy to an array, the contents of the List which are references will be copied across, so when you modify the objects in your array, they'll still refer to the same objects on the heap which are referenced from your list.

Categories

Resources