Can somebody please help me to write a DeepCopy routine for this matrix class I have ? I dont have a great deal of experience in C#.
public class Matrix<T>
{
private readonly T[][] _matrix;
private readonly int row;
private readonly int col;
public Matrix(int x, int y)
{
_matrix = new T[x][];
row = x;
col = y;
for (int r = 0; r < x; r++)
{
_matrix[r] = new T[y];
}
}
}
Thanks in advance
The simplest way of deep copying would be using some kind of serializer (for instance BinaryFormatter), but this requires not only your type to be decorated as Serializable, but also the type T.
An example implementation of that could be:
[Serializable]
public class Matrix<T>
{
// ...
}
public static class Helper
{
public static T DeepCopy<T>(T obj)
{
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
stream.Position = 0;
return (T) formatter.Deserialize(stream);
}
}
}
The issue here, is that you have no control over which type is supplied as generic type parameter. Without knowing more about which kind of types you wish to clone, an option might be to put a generic type constraint on T to only accept types that implement ICloneable.
In which case you could clone Matrix<T> like so:
public class Matrix<T> where T: ICloneable
{
// ... fields and ctor
public Matrix<T> DeepCopy()
{
var cloned = new Matrix<T>(row, col);
for (int x = 0; x < row; x++) {
for (int y = 0; y < col; y++) {
cloned._matrix[x][y] = (T)_matrix[x][y].Clone();
}
}
return cloned;
}
}
Related
I want to replace AddQuickElement and AddRangeElement with one generic function AddElement<T>. But how can i add generic element to List<Base> list. Activator do not work. Or what is better way to make this without reflection?
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
List<Base> list = new List<Base>();
AddQuickElement(list,5);
AddRangeElement(list, 5);
AddElement<Quick>(list,5);
Console.WriteLine(list.Count);
Console.ReadKey();
}
public static void AddQuickElement(List<Base> list, int number)
{
for (int i = 0; i < number; i++)
{
list.Add(new Quick());
}
}
public static void AddRangeElement (List<Base> list, int number)
{
for (int i = 0; i < number; i++)
{
list.Add(new Range());
}
}
public static void AddElement<T>(List<Base> list, int number)
{
Type type = typeof(T);
var element = Activator.CreateInstance(type);
// list.Add(element); // do not work
}
}
public abstract class Base
{
}
public class Quick:Base
{
}
public class Range : Base
{
}
}
You need to constraint the type parameter to AddElement method
public static void AddElement<T>(List<Base> list, int number) where T : Base, new()
{
for (int i = 0; i < number; i++)
{
list.Add(new T());
}
}
The type constraints where T : Base, new() mean that the type T
is derived from Base
has a public parameterless constructor.
(1) lets you add an instance of T to a List<Base>, (2) lets you create a new instance of T using new T().
I have been teaching myself generics and I wanted to try it out with a list but I struggled upon a problem I cant figure out how to "feed" the generic list to my method. What is the proper way to make a generic method "eat" my list? :)
Heres my code:
class Program<AnyDataType>
{
static void Main(string[] args)
{
jdtlist.Add("something");
jdtlist.Add("something");
jdtlist.Add("something");
Console.WriteLine(countlist(jdtlist));
Console.ReadKey();
}
static List<AnyDataType> jdtlist = new List<AnyDataType>();
public static int countlist(List<AnyDataType> list) // Yes I know this is practically useless but thats not why I am here :)
{
int listcount = 0;
for (int i = 0; i < list.Count; i++)
{
listcount++;
}
return listcount;
}
If you are writing generic method, then it should have generic parameter
public static int CountList<T>(List<T> list)
{
int listcount = 0;
for (int i = 0; i < list.Count; i++)
listcount++;
return listcount;
}
Then you can call it with any generic list
var list = new List<AnyDataType>();
// ..
Foo.CountList(list);
Same goes to classes. If you want to parametrize class with some generic type, you should provide generic argument
public class Foo<T>
As #DStanley stated, you don't need to parametrize individual methods in that case
public class Foo<T>
{
public static int CountList(List<T> list)
{
int listcount = 0;
for (int i = 0; i < list.Count; i++)
listcount++;
return listcount;
}
}
But you need to parametrize class
Foo<int>.CountList(list)
Suggested reading: Generics (C# Programming Guide)
Your problem is not passing the list to your method - that part is fine. Your problem is that you're trying to fill a "generic" list with a "specific" type (namely strings). Making a class generic means "I am not specifying the data type here - the consumer of the class will do that". So a better use case for your class would be:
class Program
{
static void Main(string[] args)
{
MyList<string>.Add("something");
MyList<string>.Add("something");
MyList<string>.Add("something");
Console.WriteLine(MyList<string>.countlist(MyList<string>.jdtlist));
Console.ReadKey();
}
}
public class MyList<AnyDataType>
{
public static List<AnyDataType> jdtlist = new List<AnyDataType>();
public static void Add(AnyDataType item)
{
jdtList.Add(item);
}
public static int countlist(List<AnyDataType> list)
{
int listcount = 0;
for (int i = 0; i < list.Count; i++)
{
listcount++;
}
return listcount;
}
This is the minimum needed to get your program to work - there are several improvements that can be made (not using static so much, etc.) but hopefully it helps you understand generics better.
You need to call the static method of the generic class via class-name including the type of the parameter:
so instead of
Console.WriteLine(countlist(jdtlist));
this:
Console.WriteLine(Program<string>.countlist(jdtlist));
Another way is to make the method generic, not the class:
public static int countlist<AnyDataType>(List<AnyDataType> list) {}
Then you can call it in these ways(with explicit type or inferred from parameter):
Program1.countlist<string>(jdtlist)
Program1.countlist(jdtlist)
Okay you have:
public static int countlist(List<AnyDataType> list)
{
int listcount = 0;
for (int i = 0; i < list.Count; i++)
{
listcount++;
}
return listcount;
}
And well, it works fine, but only if you have List<AnyDataType> to begin with.
Well, you could do:
public static int Countlist<T>(List<T> list)
{
int listcount = 0;
for (int i = 0; i < list.Count; i++)
{
listcount++;
}
return listcount;
}
Now the method itself is generic. What's more overloads will happen automatically in that you can call CountList(new List<string>()) rather than having to explicitly call CountList<strong>(new List<string>()).
But this combines with simple matters of inheritance. Consider that your CountList could work just as well with any other IEnumerable<T> implementation:
public static int Count<T>(IEnumerable<T> source)
{
int tally = 0;
foreach(var item in source)
++tally;
return tally;
}
So just as generics mean you don't have to restrict yourself to a particular type of list, so normal inheritance and interface implementation means you can work with the most general case applicable.
Not sure if it's possible, but I'd like to be able to populate a List<T> based on what T is. Presently, I have something like this (please forgive the generic names - it's for testing purposes):
public static class CollectionsClass
{
List<Object1> list1 = new List<Object1>();
List<Object2> list2 = new List<Object2>();
List<Object3> list3 = new List<Object3>();
}
public static class ActionClass
{
public static void PopulateCollections()
{
Populate(CollectionsClass.list1, 0, 10);
Populate(CollectionsClass.list2, 20, 50);
Populate(CollectionsClass.list3, 30, 100);
}
private static void Populate(dynamic list, int minLimit, int maxLimit)
{
var rnd = new Random();
int rndNum = rnd.Next(minLimit, maxLimit);
for (int i = 0; i < rndNum; i++)
{
if (list.GetType() == typeof(List<Object1>))
{
list.Add(new Object1());
}
else if (list.GetType() == typeof(List<Object2>))
{
list.Add(new Object2());
}
else if (list.GetType() == typeof(List<Object3>))
{
list.Add(new Object3());
}
else
{
// put out an error
}
}
}
}
While that code works, I'd like to shrink it by doing something like:
list.Add(new list.ObjectType());
I've been messing around with reflections and getting types all day, but I just can't seem to figure this one out.
Don't use dynamics, use generics:
static void Populate<T>(List<T> list, ...) where T: new()
{
...
for (int i=0; i<rndNum; i++)
list.Add(new T());
}
Since you're already using dynamic, you should be able to add method to handle this:
private static void AddToList<T>(List<T> list) where T : new()
{
list.Add(new T());
}
Given that, you can write:
private static void Populate(dynamic list, int minLimit, int maxLimit)
{
var rnd = new Random();
int rndNum = rnd.Next(minLimit, maxLimit);
for (int i = 0; i < rndNum; i++)
{
AddToList(list);
}
}
Try to use generic method:
public static class CollectionsClass
{
public static List<Object1> list1 = new List<Object1>();
public static List<Object2> list2 = new List<Object2>();
public static List<Object3> list3 = new List<Object3>();
}
public static class ActionClass
{
public static void PopulateCollections()
{
Populate(CollectionsClass.list1, 0, 10);
Populate(CollectionsClass.list2, 20, 50);
Populate(CollectionsClass.list3, 30, 100);
}
private static void Populate<T>(List<T> list, int minLimit, int maxLimit)
where T : new()
{
var rnd = new Random();
int rndNum = rnd.Next(minLimit, maxLimit);
for (int i = 0; i < rndNum; i++)
{
list.Add(new T());
}
}
}
Sounds like you want a combination of generics and reflection.
First of all make it generic:
void Populate<T>(List<T> mylist)
Now you know the type of your list: it's T.
All that is left is looping and creating instances of a particular type T. For this you can use Activator.CreateInstance:
for(int i = 0; i < 5; i++){
mylist.Add((T) Activator.CreateInstance(typeof(T)));
}
With this sample code:
void Main()
{
Populate<Type1>(new List<Type1>());
Populate<Type2>(new List<Type2>());
}
void Populate<T>(List<T> mylist){
for(int i = 0; i < 5; i++){
mylist.Add((T) Activator.CreateInstance(typeof(T)));
}
foreach(var item in mylist){
Console.WriteLine (item);
}
}
class Type1 { }
class Type2 { }
class Type3 { }
You get this output:
This will rely on reflection to create an instance of your object any assumes there is a public non-parameter constructor available (otherwise an exception will be thrown from the Activator).
This is not quite desirable behaviour and I realized it as soon as I saw the other answers that use the where T : new() constraint in their generic function: use this method over mine.
I'll still leave it in here for completeness though (at the very least it demonstrates a possible trap).
Use factory to extract the creation logic, reflection to get the correct type, and Activator to get the instance.
public static class TFactory
{
public static T Getmplementation<T>()
{
var typeName = typeof(T).Name;
var type = Type.GetType(typeName);
if (type != null)
return Activator.CreateInstance(type) as T;
else
throw new NotImplementedException(typeName);
}
}
Then,
List.Add(TFactory.GetImplmentation<'T>());
You can use a generic with a new constraint to achieve this:
private static void PopulateList<T>(List<T> list, int minLimit, int maxLimit)
where T : new()
{
var rnd = new Random();
int rndNum = rnd.Next(minLimit, maxLimit);
for (int i = 0; i < rndNum; i++)
{
list.Add(new T());
}
}
The constraint is that the type T must provide a default constructor. If you want to add items to a List, you do not need the dynamic keyword as you can specify List<T> as parameter type directly.
If you cannot add a default constructor, you can also provide a creator function:
private static void PopulateList<T>(List<T> list, Func<int, T> creatorFunc,
int minLimit, int maxLimit)
{
var rnd = new Random();
int rndNum = rnd.Next(minLimit, maxLimit);
for (int i = 0; i < rndNum; i++)
{
list.Add(creatorFunc(i));
}
}
You call the method like this:
var lst = new List<MyObjectType>();
PopulateList<MyObjectType>(lst, x => new MyObjectType(x), 1, 7);
In this sample, the value of i is provided to the creatorFunc that returns a new object of type MyObjectType.
I am trying to initialize a newly created empty array by using a method. Example below.
This is the structure of the code that I want to create.
var v = exClass[5,5];
v.ExtensionMethodThatWillInitilize();
What I want ExtensionMethodThatWIllInitilize to do is following:
for(int y = 0 ; y < exClass.getLength(0); y++ ) {
for(int x = 0 ; x < exClass.getLength(1); x++ ) {
v[y,x] = new instanceObject();
}}
So I came up with below code...
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var oldEx = new ExClass[10, 10];
var newEx = oldEx.init();
}
}
public class ExClass
{
public string exString
public ExClass() {
exString = " I AM NEW! YES! ";
}
}
public static class tools
{
static public ExClass[,] init(this ExClass[,] start)
{
var newArray = new ExClass[start.GetLength(0), start.GetLength(1)];
for (int y = 0; y < start.GetLength(0); y++)
{
for (int x = 0; x < start.GetLength(1); x++)
{
newArray[y, x] = new ExClass();
}
}
return newArray;
}
}
Yet the problem is that I do not know how to modify my init method so that it can take any type of array and return corresponding array that had been initialize.
I tried to use generic type T but my lack of experience seems to fail.
Summery:
1) how do you come up with a method that will initialize an empty array in a single step.
2) how do you make sure that the method can initialize any type of array(assuming that the element in the array has a constructor that does not take any argument)
Generics do work. You need to declare your method as a generic type.
I have modified the above example as follows:
class Program
{
static void Main(string[] args)
{
var oldEx = new ExClass[10, 10];
var newEx = oldEx.init<ExClass>();
}
}
public class ExClass
{
public string exString = "I AM NEW";
}
public static class tools
{
static public T[,] init<T>(this T[,] start)
{
var newArray = new T[start.GetLength(0), start.GetLength(1)];
for (int y = 0; y < start.GetLength(0); y++)
{
for (int x = 0; x < start.GetLength(1); x++)
{
newArray[y, x] = Activator.CreateInstance<T>();
}
}
return newArray;
}
}
As an answer to your comment below:
class Program
{
static void Main(string[] args)
{
var oldEx = tools.init<ExClass>(10, 10);
}
}
public class ExClass
{
public string exString = "I AM NEW";
}
public static class tools
{
static public T[,] init<T>(int x,int y)
{
var newArray = new T[x, y];
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
newArray[i, j] = Activator.CreateInstance<T>();
}
}
return newArray;
}
}
Check out this generic method, which uses the new generic constraint:
static public void Init<T>(this T[,] array) where T : new()
{
for (int y = 0; y < array.GetLength(0); y++)
{
for (int x = 0; x < array.GetLength(1); x++)
{
array[y, x] = new T();
}
}
}
The main differences from your code are:
1) The method is Init to specify a generic parameter, and there where T : new() constraint ensures that we can call new T();
2) Instead of returning a new, initialized array, I'm simply initializing the array in-place. Seems more logical. If you want, you can use your original version, but I don't understand why you'd need to.
Suppose I have an immutable value type like this:
[Serializable]
[DataContract]
public struct MyValueType : ISerializable
{
private readonly int _x;
private readonly int _z;
public MyValueType(int x, int z)
: this()
{
_x = x;
_z = z;
}
// this constructor is used for deserialization
public MyValueType(SerializationInfo info, StreamingContext text)
: this()
{
_x = info.GetInt32("X");
_z = info.GetInt32("Z");
}
[DataMember(Order = 1)]
public int X
{
get { return _x; }
}
[DataMember(Order = 2)]
public int Z
{
get { return _z; }
}
public static bool operator ==(MyValueType a, MyValueType b)
{
return a.Equals(b);
}
public static bool operator !=(MyValueType a, MyValueType b)
{
return !(a == b);
}
public override bool Equals(object other)
{
if (!(other is MyValueType))
{
return false;
}
return Equals((MyValueType)other);
}
public bool Equals(MyValueType other)
{
return X == other.X && Z == other.Z;
}
public override int GetHashCode()
{
unchecked
{
return (X * 397) ^ Z;
}
}
// this method is called during serialization
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("X", X);
info.AddValue("Z", Z);
}
public override string ToString()
{
return string.Format("[{0}, {1}]", X, Z);
}
}
It works with BinaryFormatter or DataContractSerializer but when I try to use it with protobuf-net (http://code.google.com/p/protobuf-net/) serializer I get this error:
Cannot apply changes to property
ConsoleApplication.Program+MyValueType.X
If I apply setters to the properties marked with DataMember attribute it will work but then it breaks immutability of this value type and that's not desirable to us.
Does anyone know what I need to do to get it work? I've noticed that there's an overload of the ProtoBu.Serializer.Serialize method which takes in a SerializationInfo and a StreamingContext but I've not use them outside of the context of implementing ISerializable interface, so any code examples on how to use them in this context will be much appreciated!
Thanks,
EDIT: so I dug up some old MSDN article and got a better understanding of where and how SerializationInfo and StreamingContext is used, but when I tried to do this:
var serializationInfo = new SerializationInfo(
typeof(MyValueType), new FormatterConverter());
ProtoBuf.Serializer.Serialize(serializationInfo, valueType);
it turns out that the Serialize<T> method only allows reference types, is there a particular reason for that? It seems a little strange given that I'm able to serialize value types exposed through a reference type.
Which version of protobuf-net are you using? If you are the latest v2 build, it should cope with this automatically. In case I haven't deployed this code yet, I'll update the download areas in a moment, but essentially if your type is unadorned (no attributes), it will detect the common "tuple" patten you are using, and decide (from the constructor) that x (constructor parameter)/X (property) is field 1, and z/Z is field 2.
Another approach is to mark the fields:
[ProtoMember(1)]
private readonly int _x;
[ProtoMember(2)]
private readonly int _z;
(or alternatively [DataMember(Order=n)] on the fields)
which should work, depending on the trust level. What I haven't done yet is generalise the constructor code to attributed scenarios. That isn't hard, but I wanted to push the basic case first, then evolve it.
I've added the following two samples/tests with full code here:
[Test]
public void RoundTripImmutableTypeAsTuple()
{
using(var ms = new MemoryStream())
{
var val = new MyValueTypeAsTuple(123, 456);
Serializer.Serialize(ms, val);
ms.Position = 0;
var clone = Serializer.Deserialize<MyValueTypeAsTuple>(ms);
Assert.AreEqual(123, clone.X);
Assert.AreEqual(456, clone.Z);
}
}
[Test]
public void RoundTripImmutableTypeViaFields()
{
using (var ms = new MemoryStream())
{
var val = new MyValueTypeViaFields(123, 456);
Serializer.Serialize(ms, val);
ms.Position = 0;
var clone = Serializer.Deserialize<MyValueTypeViaFields>(ms);
Assert.AreEqual(123, clone.X);
Assert.AreEqual(456, clone.Z);
}
}
Also:
it turns out that the Serialize method only allows reference types
yes, that was a design limitation of v1 that related to the boxing model etc; this no longer applies with v2.
Also, note that protobuf-net doesn't itself consume ISerializable (although it can be used to implement ISerializable).
The selected answer didn't work for me since the link is broken and I cannot see the MyValueTypeViaFields code.
In any case I have had the same exception No parameterless constructor found for my class:
[ProtoContract]
public class FakeSimpleEvent
: IPersistableEvent
{
[ProtoMember(1)]
public Guid AggregateId { get; }
[ProtoMember(2)]
public string Value { get; }
public FakeSimpleEvent(Guid aggregateId, string value)
{
AggregateId = aggregateId;
Value = value;
}
}
when deserializing it with the following code:
public class BinarySerializationService
: IBinarySerializationService
{
public byte[] ToBytes(object obj)
{
if (obj == null) throw new ArgumentNullException(nameof(obj));
using (var memoryStream = new MemoryStream())
{
Serializer.Serialize(memoryStream, obj);
var bytes = memoryStream.ToArray();
return bytes;
}
}
public TType FromBytes<TType>(byte[] bytes)
where TType : class
{
if (bytes == null) throw new ArgumentNullException(nameof(bytes));
var type = typeof(TType);
var result = FromBytes(bytes, type);
return (TType)result;
}
public object FromBytes(byte[] bytes, Type type)
{
if (bytes == null) throw new ArgumentNullException(nameof(bytes));
int length = bytes.Length;
using (var memoryStream = new MemoryStream())
{
memoryStream.Write(bytes, 0, length);
memoryStream.Seek(0, SeekOrigin.Begin);
var obj = Serializer.Deserialize(type, memoryStream);
return obj;
}
}
}
being called like var dataObject = (IPersistableEvent)_binarySerializationService.FromBytes(data, eventType);
My message class FakeSimpleEvent has indeed parameterless constructor because I want it immutable.
I am using protobuf-net 2.4.0 and I can confirm that it supports complex constructors and immutable message classes. Simply use the following decorator
[ProtoContract(SkipConstructor = true)]
If true, the constructor for the type is bypassed during
deserialization, meaning any field initializers or other
initialization code is skipped.
UPDATE 1: (20 June 2019)
I don't like polluting my classes with attributes that belong to protobuffer because the domain model should be technology-agnostic (other than dotnet framework's types of course)
So for using protobuf-net with message classes without attributes and without parameterless constructor (i.e: immutable) you can have the following:
public class FakeSimpleEvent
: IPersistableEvent
{
public Guid AggregateId { get; }
public string Value { get; }
public FakeSimpleEvent(Guid aggregateId, string value)
{
AggregateId = aggregateId;
Value = value;
}
}
and then configure protobuf with the following for this class.
var fakeSimpleEvent = RuntimeTypeModel.Default.Add(typeof(FakeSimpleEvent), false);
fakeSimpleEvent.Add(1, nameof(FakeSimpleEvent.AggregateId));
fakeSimpleEvent.Add(2, nameof(FakeSimpleEvent.Value));
fakeSimpleEvent.UseConstructor = false;
This would be the equivalent to my previous answer but much cleaner.
PS: Don't mind the IPersistableEvent. It's irrelevant for the example, just a marker interface I use somewhere else