This might be lame, but here:
public interface Interface<T>
{
T Value { get; }
}
public class InterfaceProxy<T> : Interface<T>
{
public T Value { get; set; }
}
public class ImplementedInterface: InterfaceProxy<Double> {}
Now I want to create an instance of the ImplementedInterface and initialize it's members.
Can this be done somehow like this (using initialization lists) or the same behavior can only be achieved using the constructor with Double argument?
var x = new ImplementedInteface { 30.0 };
Can be done by:
var x = new ImplementedInteface { Value = 30.0 };
var x = new ImplementedInterface() { Value = 30.0 };
The only way to achieve what you're after is if your class implements IEnumerable<T> and has an Add method:
public class MyClass : IEnumerable<double>
{
public void Add(double x){}
}
Then you can do:
MyClass mc = new MyClass { 20.0 };
Obviously that's not what you want, because that doesn't set your Value and it allows you to add multiple values:
MyClass mc = new MyClass { 20.0, 30.0 , 40.0 };
Just go with the standard object initializes like others have pointed out:
var x = new ImplementedInterface() { Value = 30.0 };
You should be able to do:
var x = new ImplementedInterface {Value = 30.0};
var instance = new ImplementedInterface { Value = 30.0 }; will work. However, this isn't really the same set of operations as C++ initializer lists -- this is an object initializer. It initializes the new instance via the default constructor and then invokes the property setters for each property.
In other words, the object is constructed before the property setters run. If you want the values for the properties set before construction of ImplementedInterface completes, you'd have to write a constructor, as you noted. This distinction in behavior usually doesn't matter, but it's good to be aware of.
I am not sure if you have a special reason to use the interfaces that way but the following code might work for you.
public class ImplementedInterface2 : List<double> { }
public class test
{
public void x()
{
var x = new ImplementedInterface2() { 30.0 };
}
}
var x = new ImplementedInterface { Value = 30.0 };
You can definitely use an initialization list, but you have to specify what 30.0 is (this is true for any initialization list, not just the code you have):
var x = new ImplementedInteface { Value=30.0 };
Related
During the development of one of my projects, I encountered an issue regarding generic types.
The project requires me to write a class that would act as a source of list objects. Suppose I had the following class:
public class TablesProvider
{
private readonly List[] _tables;
public TablesProvider()
{
// initialize the tables var here....
}
public List<TItem> GetTable<TItem>()
{
return (List<TItem>)_tables.Single(x => x is List<TItem>);
}
}
This class obviously doesn't work, because the List type is a generic type and therefore the generic arguments should be specified.
So I made an abstract type called MyList, that would be derived by a more specific type MyList<TItem> in order to escape this requirement, and edited the TablesProvider a little.
public class TablesProvider
{
private readonly MyList[] _tables;
public TablesProvider()
{
// initialize the tables var here....
}
public MyList<TItem> GetTable<TItem>()
{
return (MyList<TItem>)_tables.Single(x => x is MyList<TItem>);
}
}
public abstract class MyList
{
// ...
}
public class MyList<TItem> : MyList, IList<TItem>
{
private readonly List<TItem> _elements = new List<TItem>();
public TItem this[int index]
{
get { return _elements[index]; }
set { _elements[index] = value; }
}
// ...
}
This works quite well. There is only one problem left. Suppose I had 45 different collections, each defined with a different generic argument. What would be the best way of initializing all of those collections? I cannot use a for loop here, since generic parameters are specified at compile-time and not at runtime, and therefore a construction like this wouldn't be possible:
for (int i = 0; i < 45; i++)
_tables[i] = new MyList<GenericParameters[i]>();
My ultimate goal is to have the luxury to just do something like this...
var table = _tablesProvider.GetTable<SomeClass>();
var element = table[3];
var propertyValue = element.SomeProperty;
... without the need to cast the variable element in order to access its type-specific members.
It is probably worth mentioning that the amount of different list objects is fixed to 45. This will not change. In theory, I could initialize the array line by line, or have 45 properties or variables instead. Both of these options, however, sound as a rather cheap solution to me, but I will accept one of them if there is no other way.
Any of you got some ideas? Am I doing this completely wrong? Should I consider an other structure?
Thanks in advance.
Yes, it is possible to do what you are describing if you use reflection.
Supposing that your hypothetical GenericParameters array is an array of Types (since you can't have an array of type identifiers), you can define this helper function:
private MyList MakeList(Type t)
{
return (MyList)Activator.CreateInstance(typeof(MyList<>).MakeGenericType(t));
}
And that will allow you to do this:
public TablesProvider()
{
var GenericParameters = new[] { typeof(string), typeof(int), typeof(DateTime) };
_tables = new MyList[GenericParameters.Length];
for (int i = 0; i < GenericParameters.Length; i++)
{
_tables[i] = MakeList(GenericParameters[i]);
}
}
You can even use LINQ if you want:
public TablesProvider()
{
var GenericParameters = new[] { typeof(string), typeof(int), typeof(DateTime) };
_tables = GenericParameters.Select(MakeList).ToArray();
}
Previous answer:
Well, the reality is that you're going to have a list of 45 different types somewhere, which pretty much means you're going to have 45 different lines of similar code. So one could say the goal is to make those lines as concise as possible.
One way to do so would be to add a helper function:
private void AddTable<T>()
{
_tables.Add(new MyTable<T>());
}
(this assumes changing _tables to a List<MyTable>)
Then you could just do:
AddTable<Type1>();
AddTable<Type2>();
AddTable<Type3>();
AddTable<Type4>();
this implementation works
public class TablesProvider
{
private readonly List<object> _tables;
public TablesProvider()
{
_tables = new List<object>();
}
public IList<TItem> GetTable<TItem>()
{
var lst = (List<TItem>)_tables.SingleOrDefault(x => x is List<TItem>);
if (lst == null)
{
lst = new List<TItem>();
_tables.Add(lst);
}
return lst;
}
}
it creates List of TItem when necessary; next time it returns the same list for TItem. it is lazy initialization
so you can do invoke
var table = _tablesProvider.GetTable<SomeClass>();
without any code like this:
for (int i = 0; i < 45; i++)
_tables[i] = new MyList<GenericParameters[i]>();
it is not ThreadSafe
I've the following class
MyClass
{
public int Id {get;set;}
public string Name {get;set;}
public List<string> FriendNames {get;set;}
public MyClass()
{
FriendNames = new List<string>();
}
}
Is it correct to initialise the List like I've done or should it be
this.FriendNames = new List<string>;
Is there any difference ?
Then in my code I can create a instance like
MyClass oMyClass = new MyClass();
oMyClass.Id = 1;
oMyClass.Name = "Bob Smith";
oMyClass.FriendNames.Add("Joe King");
Here this.FriendNames = new List<string>; is exactly the same as FriendNames = new List<string>; this will count only when you will have variable with name same as your property.
like here:
public MyClass(List<string> FriendNames)
{
this.FriendNames = FriendNames; // here we have to specify which FriendNames is from this class
}
Constructor is for initializing some resources, so initializing your list there is a good idea.
You can create constructor with name and id (if you are always assigning them)
public MyClass(string name, int id)
{
FriendNames = new List<string>();
Name = name;
Id = id;
}
and change your code to:
MyClass oMyClass = new MyClass("Bob Smith", 1);
oMyClass.FriendNames.Add("Joe King");
You could do this.
private List<string> list = new List<string>();
public List<string> List
{
get { return list; }
set { list = value; }
}
Instantiating a list should be something like
FriendNames = new List<string>();
If you're asking whether the this is required, if your constructor took a list of FriendNames such that there is ambiguity in what you mean, then you'd have to use this to indicate that you want to assign it to the object's instance.
public MyClass(List<String> FriendNames)
{
this.FriendNames = FriendNames;
}
There is no real difference. So it boils down to preference.
Some people like to because it is very explicit and self commenting. Others feel that it clutters the code.
The important thing is that you are instantiating the List in the constructor. Something that too many people forget to do.
The accepted answer in this SO question has a nice list of when to use the this keyword
When do you use the “this” keyword?
If you are using this.FriendNames = new List<string>; you see that this is a class-variable with the first glance.
Especially in large classes with many variables this can be an advantage as you can easier/faster distinguish class-variables from local variables.
But as many other here stated this is up to your preference.
Where this is getting important is if you have a class and a local variable with the same name like this:
MyClass
{
public List<string> FriendNames {get;set;}
public SetMyList(List<string> FriendNames)
{
this.FriendNames = FriendNames;
}
}
In this case you have to use the this-keyword.
Use this to initialise an instance of your class
var x = new MyClass { Id = 1, Name = "Steve",
FriendNames = { "John", "Paul", "Ringo", "George" } };
And generally don't use "this." references, I rarely see it used in this way (often I use the only remnants of any kind of Hungarian notation left in my code by prefixing private fields with "_" so at least
public void DoSomething();
{
_myInt = 123;
}
private int _myInt;
public int MyInt { get { return _myInt; } }
Means I know whats going on, but I'm sure people out there won't like the "_".
It should be
FriendNames = new List<string>();
Or
FriendNames = new List<string>(123456);
if you know the capacity before upon initialization.
I want to copy values from one object to another object. Something similar to pass by value but with assignment.
For example:
PushPin newValPushPin = oldPushPin; //I want to break the reference here.
I was told to write a copy constructor for this. But this class has a lot of properties, it will probably take an hour to write a copy constructor by hand.
Is there a better way to assign an object to another object by value?
If not, is there a copy constructor generator?
Note: ICloneable is not available in Silverlight.
If you can mark the object that is to be cloned as Serializable then you can use in-memory serialization to create a copy. Check the following code, it has the advantage that it will work on other kinds of objects as well and that you don't have to change your copy constructor or copy code each time an property is added, removed or changed:
class Program
{
static void Main(string[] args)
{
var foo = new Foo(10, "test", new Bar("Detail 1"), new Bar("Detail 2"));
var clonedFoo = foo.Clone();
Console.WriteLine("Id {0} Bar count {1}", clonedFoo.Id, clonedFoo.Bars.Count());
}
}
public static class ClonerExtensions
{
public static TObject Clone<TObject>(this TObject toClone)
{
var formatter = new BinaryFormatter();
using (var memoryStream = new MemoryStream())
{
formatter.Serialize(memoryStream, toClone);
memoryStream.Position = 0;
return (TObject) formatter.Deserialize(memoryStream);
}
}
}
[Serializable]
public class Foo
{
public int Id { get; private set; }
public string Name { get; private set; }
public IEnumerable<Bar> Bars { get; private set; }
public Foo(int id, string name, params Bar[] bars)
{
Id = id;
Name = name;
Bars = bars;
}
}
[Serializable]
public class Bar
{
public string Detail { get; private set; }
public Bar(string detail)
{
Detail = detail;
}
}
There is a protected member called "MemberwiseClone", you can write this in your class...
public MyClass Clone(){
return (MyClass)this.MemberwiseClone();
}
then you can access..
MyClass newObject = oldObject.Clone();
The only way (that I'm aware of) to do this, and do it correctly, is to implement the copy yourself. Take for example:
public class FrobAndState
{
public Frob Frobber { get; set;}
public bool State { get; set; }
}
public class Frob
{
public List<int> Values { get; private set; }
public Frob(int[] values)
{
Values = new List<int>(values);
}
}
In this example you'd need to know how Frob was implemented, i.e. the fact that you need to call the constructor to create a copy of it as Values is read-only, to be able to make a copy of a given instance of FrobAndState.
Also - you couldn't just implement FrobAndState.Copy thusly:
public class FrobAndState
{
// ... Properties
public FrobAndState Copy()
{
var new = new FrobAndState();
new.State = this.State;
new.Frobber = this.Frobber;
}
}
Because both the instance of FrobAndState that you called .Copy() on, and the new instance would both have a reference to the same instance of Frobber.
In short, copying things is hard and any Copy implementation is difficult to get right.
C# does not have a copy constructor. There are different ways to tackle this. At the OOP level you could use inheritance or aggregation. AutoMapper might also be worth a try.
I want to copy values from one object
to another object. Something similiar
to pass by value but with assignment.
What do you mean by "with assignment"? If you mean that you want people to be able to say:
a = b;
And for you to define what = means, the only way you can do that in C# is if b is a different type to a and you've defined an implicit conversion (or more tenuously, if a stands for something of the form x.Y where Y is a property with a setter). You can't override = for a simple assignment between identical types in C#.
I was told to write a copy constructor
for this. But this class has alot of
properties, it will probably take an
hour to write a copy constructor by
hand.
If that's really true, then I would guess that you have a different problem. Your class is too big.
If you make your class Serializable you could Serialize it to a MemoryStream and Deserialize to a new instance.
If you want copy-on-assignment you should be using a struct instead of a class. But be careful, it is easy to make subtle mistakes. It is highly recommended that all stucts be immmutable to reduce the chance for error.
Though, this may not answer your question directly, but to add a cent; usually the term Clone is linked with shallow copy(referenced objects). To have a deep copy, I believe you will need to look into the some creational pattern(prototype?). The answer to this question might help.
You implement Justin Angel's method of cloning objects in Silverlight
using System;
using System.Reflection;
using System.Windows;
namespace JustinAngelNet.Silverlight.Framework
{
public static class SilverlightExtensions
{
public static T Clone<T>(T source)
{
T cloned = (T) Activator.CreateInstance(source.GetType());
foreach (PropertyInfo curPropInfo in source.GetType().GetProperties())
{
if (curPropInfo.GetGetMethod() != null
&& (curPropInfo.GetSetMethod() != null))
{
// Handle Non-indexer properties
if (curPropInfo.Name != "Item")
{
// get property from source
object getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {});
// clone if needed
if (getValue != null && getValue is DependencyObject)
getValue = Clone((DependencyObject) getValue);
// set property on cloned
if (getValue != null)
curPropInfo.GetSetMethod().Invoke(cloned, new object[] {getValue});
}
// handle indexer
else
{
// get count for indexer
int numberofItemInColleciton =
(int)
curPropInfo.ReflectedType.GetProperty("Count").GetGetMethod().Invoke(source, new object[] {});
// run on indexer
for (int i = 0; i < numberofItemInColleciton; i++)
{
// get item through Indexer
object getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {i});
// clone if needed
if (getValue != null && getValue is DependencyObject)
getValue = Clone((DependencyObject) getValue);
// add item to collection
curPropInfo.ReflectedType.GetMethod("Add").Invoke(cloned, new object[] {getValue});
}
}
}
}
return cloned;
}
}
}
Then you can do this
MyClass newObject = SilverlightExtensions.Clone(oldObject);
I have a class with a static factory method on it. I want to call the factory to retrieve an instance of the class, and then do additional initialization, preferablly via c# object initializer syntax :
MyClass instance = MyClass.FactoryCreate()
{
someProperty = someValue;
}
vs
MyClass instance = MyClass.FactoryCreate();
instance.someProperty = someValue;
No. Alternatively you could accept a lambda as an argument, which also gives you full control in which part of the "creation" process will be called. This way you can call it like:
MyClass instance = MyClass.FactoryCreate(c=>
{
c.SomeProperty = something;
c.AnotherProperty = somethingElse;
});
The create would look similar to:
public static MyClass FactoryCreate(Action<MyClass> initalizer)
{
MyClass myClass = new MyClass();
//do stuff
initializer( myClass );
//do more stuff
return myClass;
}
Another option is to return a builder instead (with an implicit cast operator to MyClass). Which you would call like:
MyClass instance = MyClass.FactoryCreate()
.WithSomeProperty(something)
.WithAnotherProperty(somethingElse);
Check this for the builder
Both of these versions are checked at compile time and have full intellisense support.
A third option that requires a default constructor:
//used like:
var data = MyClass.FactoryCreate(() => new Data
{
Desc = "something",
Id = 1
});
//Implemented as:
public static MyClass FactoryCreate(Expression<Func<MyClass>> initializer)
{
var myclass = new MyClass();
ApplyInitializer(myclass, (MemberInitExpression)initializer.Body);
return myclass ;
}
//using this:
static void ApplyInitializer(object instance, MemberInitExpression initalizer)
{
foreach (var bind in initalizer.Bindings.Cast<MemberAssignment>())
{
var prop = (PropertyInfo)bind.Member;
var value = ((ConstantExpression)bind.Expression).Value;
prop.SetValue(instance, value, null);
}
}
Its a middle between checked at compile time and not checked. It does need some work, as it is forcing constant expression on the assignments. I think that anything else are variations of the approaches already in the answers. Remember that you can also use the normal assignments, consider if you really need any of this.
Yes. You can use object initializer for already created instance with the following trick. You should create a simple object wrapper:
public struct ObjectIniter<TObject>
{
public ObjectIniter(TObject obj)
{
Obj = obj;
}
public TObject Obj { get; }
}
And now you can use it like this to initialize your objects:
new ObjectIniter<MyClass>(existingInstance)
{
Obj =
{
//Object initializer of MyClass:
Property1 = value1,
Property2 = value2,
//...
}
};
P.S. Related discussion in dotnet repository:
https://github.com/dotnet/csharplang/issues/803
You can use an extension method such as the following:
namespace Utility.Extensions
{
public static class Generic
{
/// <summary>
/// Initialize instance.
/// </summary>
public static T Initialize<T>(this T instance, Action<T> initializer)
{
initializer(instance);
return instance;
}
}
}
You would call it as follows:
using Utility.Extensions;
// ...
var result = MyClass.FactoryCreate()
.Initialize(x =>
{
x.someProperty = someValue;
x.someProperty2 = someValue2;
});
+1 on "No".
Here's an alternative to the anonymous object way:
var instance = MyClass.FactoryCreate(
SomeProperty => "Some value",
OtherProperty => "Other value");
In this case FactoryCreate() would be something like:
public static MyClass FactoryCreate(params Func<object, object>[] initializers)
{
var result = new MyClass();
foreach (var init in initializers)
{
var name = init.Method.GetParameters()[0].Name;
var value = init(null);
typeof(MyClass)
.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase)
.SetValue(result, value, null);
}
return result;
}
No, the object initializer can only be used on a call to "new" with the constructor. One option might be to add some additional args to your factory method, to set those values at object creation inside the factory.
MyClass instance = MyClass.FactoryCreate(int someValue, string otherValue);
Like everyone said, no.
A lambda as an argument has already been suggested.
A more elegant approach would be to accept an anonymous and set the properties according to the object. i.e.
MyClass instance = MyClass.FactoryCreate(new {
SomeProperty = someValue,
OtherProperty = otherValue
});
That would be much slower though, since the object would have to be reflected on for all the properties.
No, that's something you can only do 'inline'. All the factory function can do for you is to return a reference.
The simple demo below captures what I am trying to do. In the real program, I have to use the object initialiser block since it is reading a list in a LINQ to SQL select expression, and there is a value that that I want to read off the database and store on the object, but the object doesn't have a simple property that I can set for that value. Instead it has an XML data store.
It looks like I can't call an extension method in the object initialiser block, and that I can't attach a property using extension methods.
So am I out of luck with this approach? The only alternative seems to be to persuade the owner of the base class to modify it for this scenario.
I have an existing solution where I subclass BaseDataObject, but this has problems too that don't show up in this simple example. The objects are persisted and restored as BaseDataObject - the casts and tests would get complex.
public class BaseDataObject
{
// internal data store
private Dictionary<string, object> attachedData = new Dictionary<string, object>();
public void SetData(string key, object value)
{
attachedData[key] = value;
}
public object GetData(string key)
{
return attachedData[key];
}
public int SomeValue { get; set; }
public int SomeOtherValue { get; set; }
}
public static class Extensions
{
public static void SetBarValue(this BaseDataObject dataObject,
int barValue)
{
/// Cannot attach a property to BaseDataObject?
dataObject.SetData("bar", barValue);
}
}
public class TestDemo
{
public void CreateTest()
{
// this works
BaseDataObject test1 = new BaseDataObject
{ SomeValue = 3, SomeOtherValue = 4 };
// this does not work - it does not compile
// cannot use extension method in the initialiser block
// cannot make an exension property
BaseDataObject test2 = new BaseDataObject { SomeValue = 3, SomeOtherValue = 4, SetBarValue(5) };
}
}
One of the answers (from mattlant) suggests using a fluent interface style extension method. e.g.:
// fluent interface style
public static BaseDataObject SetBarValueWithReturn(this BaseDataObject dataObject, int barValue)
{
dataObject.SetData("bar", barValue);
return dataObject;
}
// this works
BaseDataObject test3 = (new BaseDataObject { SomeValue = 3, SomeOtherValue = 4 }).SetBarValueWithReturn(5);
But will this work in a LINQ query?
Object Initializers are just syntactic sugar that requires a clever compiler, and as of the current implementation you can't call methods in the initializer.
var x = new BaseDataObject { SomeValue = 3, SomeOtherValue = 4 };
Will get compiler to something like this:
BaseDataObject tempObject = new BaseDataObject();
tempObject.SomeValue = 3;
tempObject.SomeOtherValue = 4;
BaseDataObject x = tempObject;
The difference is that there can't be any synchronization issues. The variable x get's assigned the fully assigned BaseDataObject at once, you can't mess with the object during it's initialization.
You could just call the extension method after the object creation:
var x = new BaseDataObject { SomeValue = 3, SomeOtherValue = 4 };
x.SetBarValue()
You could change SetBarValue to be a property with get/set that can be assigned during initialization:
public int BarValue
{
set
{
//Value should be ignored
}
}
Or, you could subclass / use the facade pattern to add the method onto your object:
public class DataObjectWithBarValue : BaseDataObject
{
public void BarValue
{
set
{
SetData("bar", value);
}
get
{
(int) GetData("bar");
}
}
}
No but you could do this....:
BaseDataObject test2 = (new BaseDataObject { SomeValue = 3, SomeOtherValue = 4}).SetBarValue(5);
ANd have your extension return the object like Linq Does.
EDIT: This was a good thought untill i reread and saw that the base class was developed by a third person: aka you dont have the code. Others here have posted a correct solution.
Even better:
public static T SetBarValue<T>(this T dataObject, int barValue)
where T : BaseDataObject
{
dataObject.SetData("bar", barValue);
return dataObject;
}
and you can use this extension method for derived types of BaseDataObject to chain methods without casts and preserve the real type when inferred into a var field or anonymous type.
static T WithBarValue<T>(this T dataObject, int barValue)
where T : BaseDataObject
{ dataObject.SetData("bar", barValue);
return dataObject;
}
var x = new BaseDataObject{SomeValue=3, OtherValue=4}.WithBarValue(5);
Is extending the class a possibility? Then you could easily add the property you need.
Failing that, you can create a new class that has similar properties that simply call back to a private instance of the class you are interested in.
Right, having learned from the answerers, the short answer to "Is there any way to use an extension method in an object initializer block in C#?" is "No."
The way that I eventually solved the problem that I faced (similar, but more complex that the toy problem that I posed here) was a hybrid approach, as follows:
I created a subclass, e.g.
public class SubClassedDataObject : BaseDataObject
{
public int Bar
{
get { return (int)GetData("bar"); }
set { SetData("bar", value); }
}
}
Which works fine in LINQ, the initialisation block looking like
SubClassedDataObject testSub = new SubClassedDataObject
{ SomeValue = 3, SomeOtherValue = 4, Bar = 5 };
But the reason that I didn't like this approach in the first place is that these objects are put into XML and come back out as BaseDataObject, and casting back was going to be an annoyance, an unnecessary data copy, and would put two copies of the same object in play.
In the rest of the code, I ignored the subclasses and used extension methods:
public static void SetBar(this BaseDataObject dataObject, int barValue)
{
dataObject.SetData("bar", barValue);
}
public static int GetBar(this BaseDataObject dataObject)
{
return (int)dataObject.GetData("bar");
}
And it works nicely.