What would be the best way to write a generic copy constructor function for my c# classes?
They all inherit from an abstract base class so I could use reflection to map the properties, but I'm wondering if there's a better way?
A copy constructor basically means you have a single parameter, which is the object you're going to copy.
Also, do a deep copy, not a shallow copy.
If you don't know what deep and shallow copies are, then here's the deal:
Suppose you're copying a class that has a single row of integers as field.
A shallow copy would be:
public class Myclass()
{
private int[] row;
public MyClass(MyClass class)
{
this.row = class.row
}
}
deep copy is:
public class Myclass()
{
private int[] row;
public MyClass(MyClass class)
{
for(int i = 0; i<class.row.Length;i++)
{
this.row[i] = class.row[i];
}
}
}
A deep copy really gets the actuall values and puts them in a new field of the new object, whilst a shallow copy only copies the pointers.
With the shallow copy, if you set:
row[3] = 5;
And then print both rows, both prints will have 5 as value of the 4th number.
With a deep copy however, only the first print will have this, since the rows don't have the same pointers.
Avoid reflection if you can. Each class should have the responsibility of copying its own properties, and send it further to the base method.
You can create a shallow copy efficiently with reflection by pre-compiling it, for example with Expression. For example, like so.
For deep copies, serialization is the most reliable approach.
Here's a constructor that I'm using. Note that this is a shallow constructor, and rather simplistic, due to the nature of my base class. Should be good enough to get you started.
public partial class LocationView : Location
{
public LocationView() {}
// base class copy constructor
public LocationView(Location value) {
Type t = typeof(Location);
PropertyInfo[] properties = t.GetProperties();
foreach (PropertyInfo pi in properties)
{
pi.SetValue(this, pi.GetValue(value, null), null);
}
}
public Quote Quote { get; set; }
}
You may reference valueinjecter and fasterflect nuget packages and use:
public class Myclass()
{
private string _property;
public MyClass(MyClass obj)
{
this.InjectFrom(obj.DeepClone());
}
}
Related
I have a question about creating an immutable struct inside a class definition. I want to define the struct outside the class but use that same struct type in the class definition while maintaining immutability. Will the code below achieve this?
namespace space
{
class Class1
{
public Struct {get; set;}
}
public Struct
{
public Struct(string strVar)
{
StructVar = strVar;
}
public string StructVar {get;}
}
}
Also, if I have a struct within a struct like:
class Class1
{
public Struct2 {get; set;}
}
public struct Struct2
{
public Struct2(string str, InStruct inStrct)
{
StrVar = str;
InStruct = inStrct;
}
public string StrVar {get;}
public InStruct InStruct {get;}
}
public struct InStruct
{
public InStruct(Array ary)
{
StrArray = ary
}
public Array StrArray {get;}
}
Does this also maintain immutability?
Lastly, if the size of the array in the InStruct is likely to be quite long, should I not use a struct at all and just put the array itself into the class definition instead? Am I just going struct crazy?
My concern is that because I'm doing a {set;} in the class definition that I'm breaking a rule somewhere. I would put the struct in the class definition itself but I didn't like to have to continuously call class constructors over and over to create each struct, that kind of seemed to defeat the purpose of using a struct in the first place.
It's a little difficult to give a complete answer without understanding exactly what you are trying to accomplish, but I'll start with a few important distinctions.
First, in C#, the struct/class distinction isn't about mutability per se. You can have a immutable class, like this one
public class CannotBeMutated
{
private string someVal;
public CannotBeMutated(string someVal)
{
_someVal = someVal
}
public string SomeVal => _someVal;
}
and a mutable struct, like this one
// This is not at all idiomatic C#, please don't use this as an example
public struct MutableStruct
{
private string _someVal;
public MutableStruct(string someVal)
{
_someVal = someVal;
}
public void GetVal()
{
return _someVal
}
public void Mutate(string newVal)
{
_someVal = newVal;
}
}
Using the above struct I can do this
var foo = new MutableStruct("Hello");
foo.mutate("GoodBye");
var bar = foo.GetVal(); // bar == "GoodBye"!
The difference between structs and classes is in variable passing semantics. When an object of a value type (e.g. a struct) is assigned to a variable, passed as a parameter to or returned from a method (including a property getter or setter) a copy of the object is made before it is passed to the new function context. When a object of a reference type is passed as a parameter to or returned from a method, no copy is made, because we only pass a reference to the object's location in memory, rather than a copy of the object.
An additional point on struct 'copying'. Imagine you have a struct with a field that is a reference type, like this
public struct StructWithAReferenceType
{
public List<string> IAmAReferenceType {get; set;}
}
When you pass an instance of this struct into a method, a copy of the reference to the List will be copied, but the underlying data will not. So if you do
public void MessWithYourSruct(StructWithAReferenceType t)
{
t.IAmAReferenceType.Add("HAHA");
}
var s = new StructWithAReferenceType { IAmAReferenceType = new List()};
MessWithYourSruct(s);
s.IAmAReferenceType.Count; // 1!
// or even more unsettling
var s = new StructWithAReferenceType { IAmAReferenceType = new List()};
var t = s; // makes a COPY of s
s.IAmAReferenceType.Add("hi");
t.IAmAReferenceType.Count; // 1!
Even when a struct is copied, its reference type fields still refer to the same objects in memory.
The immutable/mutable and struct/class differences are somewhat similar, insofar as they are both about where and whether you can change the contents of an object in your program, but they are still very distinct.
Now on to your question. In your second example, Class1 is not immutable, as you can mutate the value of Struct2 like this
var foo = new Class1();
foo.Struct2 = new Struct2("a", 1);
foo.Struct2 // returns a copy of Struct2("a", 1);
foo.Struct2 = new Struct2("b", 2);
foo.Struct2 // returns a copy of Struct2("b", 2);
Struct2 is immutable, as there is no way for calling code to change the values of StrVar or InVar once. InStruct is similarly immutable. However, Array is not immutable. So InStruct is an immutable container for a mutable value. Similar to if you had a ImmutableList<List<string>>. While you can guarantee calling code does not change the value of InStruct.StrArray to a different array, you can do nothing about calling code changing the value of the objects in the Array.
Finally, some generic advice related to your example.
First, mutable structs, or structs with mutable fields, are bad. The examples above should point to why structs with mutable fields are bad. And Eric Lippert himself has a great example of how terrible mutable structs can be on his blog here
Second, for most developers working in C# there's almost never a reason to create a user defined value type (i.e. a struct). Objects of value types are stored on the stack, which makes memory access to them very fast. Objects of reference types are stored on the heap, and so are slower to access. But in the huge majority of C# programs, that distinction is going to be dwarfed by the time cost of disk I/O, network I/O, reflection in serialization code, or even initialization and manipulation of collections. For ordinary developers who aren't writing performance-critical standard libraries, there's almost no reason to think about the performance implications of the difference. Heck, developers in Java, Python, Ruby, Javascript and many other languages get by in languages totally without user-defined value types. Generally, the added cognitive overhead they introduce for developers is almost never worth any benefit you might see. Also, remember that large structs must be copied whenever they are passed or assigned to a variable, and can actually be a performance problem.
TL;DR you probably shouldn't use structs in your code, and they don't really have anything to do with immutability.
How do I prevent dictionary items from modification outside of my class?
I have to expose collection of objects as a property, but then everyone can do everything with my objects. I tried to use ReadOnlyDictionary to wrap my public property, but IntegerValue property still can be modified from outside.
Sample code is below:
internal class MyRefClass
{
public object ReferenceStrig;
public int IntegerValue;
public MyRefClass()
{
ReferenceStrig = "Initialized string";
IntegerValue = 100;
}
}
class Program
{
static void Main(string[] args)
{
var writableDict = new Dictionary<int, MyRefClass>();
writableDict.Add(1,new MyRefClass());
ReadOnlyDictionary<int, MyRefClass> dict = new ReadOnlyDictionary<int, MyRefClass>(writableDict);
MyRefClass variable;
dict.TryGetValue(1, out variable); #get an object from dictionary
variable.IntegerValue = 0; #changing property of the object
writableDict.TryGetValue(1, out variable); #get the same object once again
#now property variable.IntegerValue == 0 instead of 100!
}
}
If you want to expose an object to "Client code" and yet you want the object not to be modified then you must return a "Immutable type". Either in the form of immutable class or an interface with only readonly properties.
This also means that all the properties and nested properties and so on of your type should also be "Immutable" otheriwse they will be still able to modify the nested members. In other words All types in object graph of the type you expose must be Immutable.
Another option is to clone the object and return the copy and forget about the modifications. But be sure you're doing a Deep-Copy and not Shallow-Copy. Shallow copy suffers from aforementioned problem.
Make your class immutable, for example:
class MyImmutableRefClass
{
public readonly object ReferenceStrig;
public readonly int IntegerValue;
public MyImmutableRefClass(): this("Initialized string", 100)
{
}
public MyImmutableRefClass(string referenceStrig, int integerValue)
{
ReferenceStrig = referenceStrig;
IntegerValue = integerValue;
}
}
This isn't really enough if ReferenceStrig is an object which itself isn't immutable. It works for this particular example because it can only be a string (which is itself immutable).
But if it was some other type, then that type would have to be immutable itself - and (recursively) any public fields and properties that it contains would also have to be immutable. (I call that "deep-immutable".)
Here's an interesting series of articles on immutability in C#:
http://blogs.msdn.com/b/ericlippert/archive/2007/11/13/immutability-in-c-part-one-kinds-of-immutability.aspx
I'm having some problems with encapsulation in C#. There are two specific scenarios that are causing me problems and I believe the issue is related.
Scenario #1
I have a class definition that looks something like this
class MyClass
{
private int _someField;
private OtherClass _otherClass;
public int someField
{
get { return _someField; }
set { _someField = value; }
}
public OtherClass otherClass
{
get { return _otherClass; }
set { _otherClass = value; }
}
}
If I then try and do something like this in a new piece of code
MyClass theClass = new MyClass();
theClass.otherClass.XYZ += 1;
I get told Cannot Modify the return value of 'MyClass.otherClass' because it is not a variable.
Scenario 2#
public partial class trksegType
{
private wptType[] trkptField;
private extensionsType extensionsField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("trkpt")]
public wptType[] trkpt
{
get
{
return this.trkptField;
}
set
{
this.trkptField = value;
}
}
}
If I now try and foreach through the wptType array:
foreach (wptType way in trk.trkseg[i])
I get told - foreach statement cannot operate on variables of type 'trksegType' because 'trksegType' does not contain a public definition for 'GetEnumerator'
Even though an array should implicitly allow enumeration.
Can anyone explain what's going on and what I can do to get around this problem, whilst still maintaining best practices.
For scenario 1, I suspect that OtherClass has been defined as a struct. When a struct is accessed from a property accessor a new copy of the struct is created and returned (structs are value types). Changing a property on this new copy will have no effect on the original struct.
The C# compiler detects this and raises that slightly obscure error.
Scenario 1:
The reason is very likely because your OtherClass is a struct and not a class. Value sematics are a bit tricky and mutable value types are considered harmful. So you either want to make OtherClass a class and not a struct or you do something along those lines:
struct OtherClass
{
public int XYZ { get; }
public OtherClass(int xyz)
{
XYZ = xyz;
}
public OtherClass AddToXYZ(int count)
{
return new OtherClass(this.XYZ + count);
}
}
Then you can do
myClass.otherClass = myClass.otherClass.AddToXYZ(1);
Scenario 2:
You either need to implement IEnumerable on trksegType to enumerate over trkpt or actually access trkpt for the enumeration.
In General:
You have violated encapsulation in both scenarios by accessing objects through other objects. Have a look here: http://www.csharp-station.com/Tutorials/lesson19.aspx
You also should consider using better (more explicit) names for your objects. mttng vwls ds nt ncrs rdblty.
(You really shouldn’t post two questions in one.)
Scenario 1
Cannot Modify the return value of 'MyClass.otherClass' because it is not a variable.
This error happens because OtherClass is not a class, but a struct — also called a value type. This means that accessing MyClass.otherClass copies the value instead of returning a reference. You would be modifying this copy, which would be pointless. The compiler catches this because it is always a bug and never useful.
Scenario 2
foreach (wptType way in trk.trkseg[i])
You haven’t told us what trkseg[i] is, but if it is of the type trksegType, then the answer is: because trksegType doesn’t allow any enumeration. It does not implement IEnumerable, IEnumerable<T>, nor does it have a GetEnumerator method of its own.
Perhaps you meant to write:
foreach (wptType way in trk.trkseg[i].trkpt)
because trkpt is an array of wptType. (You might have found this error sooner if you used more meaningful variable names instead of weird combinations of letters that make no sense.)
I can't see anything wrong with your first example - so double check that the sample that errors really does and correct if not.
In the second instance, it looks like you're trying to iterate on an instance of trksegType, rather than the contained trkpt property. Try foreach (wptType way in trk.trkseg[i].trkpt) instead.
In C#, I am defining a static field of a specific class. From within the class, I want to be able to display the name of the static field, pretty much like this:
public class Unit {
public string NameOfField { get { return ...; } }
}
public static Unit Hectare = new Unit();
If I now access:
Hectare.NameOfField
I want it to return:
Hectare
I know there is a static function System.Reflection.MethodBase.GetCurrentMethod(), but as far as I can tell there is no way to get the name of the instance containing this current method?
There is also the System.RuntimeFieldHandle structure, but I have not been able to identify any GetCurrentFieldHandle() method.
I am not sure if I am missing something obvious?
Any help on this is very much appreciated.
You should not count on variable names in you developments as they do not exits at runtime.
It's better to initialize Unit with a name directly:
public class Unit {
public Unit(string name)
{
NameOfField = name;
}
public string NameOfField { get; private set;} }
}
public static Unit Hectare = new Unit("Hectare");
Only way around this will be to store that information in the class:
public static Unit Hectare = new Unit("Hectare");
When your code is compiled all variable names are lost and replaced by internal references. There is no way to get that name again.
You can use Reflection to obtain class Fields and properties. Like below:
Suppose you have class with one property:
class Test
{
public static string MySupperField
{
get
{
return "Some symbols here";
}
}
}
......
You can read the property name in such way:
public string[] GetClassStaticNames(Type T)
{
string[] names;
System.Reflection.PropertyInfo[] props = T.GetProperties(); // This will return only properties not fields! For fields obtaining use T.GetFields();
names = new string[props.Count()];
for (int i = 0; i < props.Count(); i++)
{
names[i] = props[i].Name;
}
return names;
}
Hope this will help.
[EDIT]
Returning to your question - No you cant obtain name of current variable.
What you are asking about cant be done because of classes nature, they are objects in memory and reference to one object can be held in many variables, and when you are requesting value of instance field or property it will be actually performed operation with object in memory not with variable wich holds reference to that object. So obtaining name of variable wich holds reference to current instance have no sence
Thanks everyone who has taken the time to answer and discuss my question.
Just to let you know, I have implemented a solution that is sufficient for my needs. The solution is not general, and it has some pitfalls, but I'd thought I share it anyway in case it can be of help to someone else.
This is in principle what the class that is used when defining fields looks like:
public class Unit : IUnit {
public NameOfField { get; set; }
...
}
As you can see, the class implements the IUnit interface, and I have provided a public setter in the NameOfField property.
The static fields are typically defined like this within some containing class:
public static Unit Hectare = new Unit();
My solution is to set the NameOfField property through reflection before the field is used in the implementation.
I do this through a static constructor (that of course needs to be invoked before the Unit fields are accessed.
I use Linq to traverse the executing assembly for the relevant fields, and when I have detected these fields (fields which type implements the IUnit interface), I set the NameOfField property for each of them using the Any extension method:
Assembly.GetExecutingAssembly().GetTypes().
SelectMany(type => type.GetFields(BindingFlags.Public | BindingFlags.Static)).
Where(fieldInfo => fieldInfo.FieldType.GetInterfaces().Contains(typeof(IUnit))).
Any(fieldInfo =>
{
((IUnit)fieldInfo.GetValue(null)).NameOfField= fieldInfo.Name;
return false;
});
There are some shortcomings with this approach:
The static constructor has to be invoked through manual intervention before any Unit fields can be accessed
The NameOfField setter is public. In my case this is no problem, but it might be when applied in other scenarios. (I assume that the setter could be made private and invoked through further reflection, but I have not taken the time to explore that path further.)
... ?
Either way, maybe this solution can be of help to someone else than me.
I swear I have seen an example of this but have been googling for a bit and can not find it.
I have a class that has a reference to an object and need to have a GET; method for it. My problem is that I do not want anyone to be able to fiddle with it, i.e. I want them to get a read only version of it, (note I need to be able to alter it from within my class).
Thanks
No, there's no way of doing this. For instance, if you return a List<string> (and it's not immutable) then callers will be able to add entries.
The normal way round this is to return an immutable wrapper, e.g. ReadOnlyCollection<T>.
For other mutable types, you may need to clone the value before returning it.
Note that just returning an immutable interface view (e.g. returning IEnumerable<T> instead of List<T>) won't stop a caller from casting back to the mutable type and mutating.
EDIT: Note that apart from anything else, this kind of concern is one of the reasons why immutable types make it easier to reason about code :)
Return a reference to a stripped-down interface:
interface IFoo
string Bar { get; }
class ClassWithGet
public IFoo GetFoo(...);
If the object isn't too complicated/extensive then write an wrapper around it.
for example:
class A {
public string strField = 'string';
public int intField = 10;
}
class AWrapper {
private A _aObj;
public AWrapper(A aobj) {
_aObj = A;
}
public string strField {
get {
return _aObj.strField;
}
}
public int intField {
get {
return _aObj.intField;
}
}
}
So now all you do is give your client code an instance of the AWrapper class so that they may only use what you allow them to see.
this may get a bit complicated and may not scale well if your base class is not set in stone, but for most simple situation it may just do the trick. I think this is called a facade pattern(but don't quote me on that =) )
This isn't possible. Get and set accessors to reference types get and set the reference to the object. You can prevent changes to the reference by using a private (or internal) setter, but you cannot prevent changes to the object itself if it's exposed by a getter.
Your question reads like you're looking for:
public PropertyName { get; private set; }
But then, given the answers so far I'm not sure I'm interpreting your question correctly. Besides, who am I to question Jon Skeet? :)
i agree with ReadOnlyCollection
See my simple code:
private List<Device> _devices;
public readonly System.Collections.ObjectModel.ReadOnlyCollection<Device> Devices
{
get
{
return (_devices.AsReadOnly());
}
}
ReadOnlyCollection dosen't has Add method so user cant add properties to it.BUT ther is no warranty that if user can modify objects by calling their methods....
I have faced this problem in a certain way.
I have a CategoryViewModel class, which have a property Category that I want private read-only :
public CategoryViewModel
{
private Category { get; }
}
In fact, I want it to be exported as read-only to other class. However I can't do such thing.
In my case (maybe it will help some other guys), I want to add it to a repository. The only way that I've found is to have a function with the repository as param 1, and an Action as param 2 :
public void ApplyAction(ICategoryRepository repo, Action<ICategoryRepository, Category> action)
{
action(repo, Category);
}
Like that, from elsewhere, I can do such thing :
categoryViewModel.ApplyAction(_repository, (r, c) => r.MarkForInsertOrUpdate(c));
This can help other to expose there property only for certains cases and can manage them.