i'm trying to minimize use of constractors in derived classes, and have a base class to hold common properties
so i tried as follows
public class sharedData
{
public string GlobMeta;
public int GlobValue;
public sharedData(string meta, int value)
{
GlobMeta = meta;
GlobValue= value;
}
}
public class derivedData: sharedData
{
public string test;
test = string.Format("Shared meta = {0}, Shared Value = {1}",GlobMeta, GlobValue);
}
then use
var shared = new sharedData("desc", 1);
var derived = new derivedData();
var testData = derived.test;
so when i will create instance of derived it will use base (shared) values
wich is common to all derived classes.
how can i implement this, as my idea was to use less memory with large collections of data. and also clean code and ease of use.
You have declared a based class, sharedData, without parameterless constructor. Therefore, any class that inherit that class must define a base constructor. You can't rely on the the compiler do job the job for you anymore.
public class derivedData : sharedData
{
public string test;
public derivedData(string meta, int value) : base(meta, value)
{
// you can't do assignment in the class scope, unless it can be done statically, it has to be inside a method block
test = string.Format("Shared meta = {0}, Shared Value = {1}", GlobMeta, GlobValue);
}
// or, if you prefer to have a parameterless ctor
public derivedData() : base("a default value for meta", default(int))
{
test = string.Format("Shared meta = {0}, Shared Value = {1}", GlobMeta, GlobValue);
}
}
EDIT: It seems that you are using this for global settings, in that case, you need to mark GlobMeta and GlobValue as static. Otherwise they won't be "shared" at all between different instance of sharedData/derivedData.
You should consider rewriting it as this :
public static class SharedData
{
public static string Meta { get; private set; }
public static int Value { get; private set; }
public static void SetData(string meta, int value)
{
Meta = meta;
Value = value;
}
}
public class DerivedData
{
public string Test
{
get { return string.Format("Shared meta = {0}, Shared Value = {1}", SharedData.Meta, SharedData.Value); }
}
}
EDIT 2 : If you need to have various instances of these, use the following :
public class SharedData
{
public string Meta { get; set; }
public int Value { get; set; }
public SharedData(string meta, int value)
{
Meta = meta;
Value = value;
}
}
public class DerivedData : SharedData
{
public string Test
{
get { return string.Format("Shared meta = {0}, Shared Value = {1}", Meta, Value); }
}
public DerivedData(string meta, int value) : base(meta, value)
{
}
// note: this is a copy ctor, changing data after this has been created, will not affect this.
public DerivedData(SharedData data) : base(data.Meta, data.Value)
{
}
}
I was thinking along the same lines as Xiaoy312, and wrote this while he was posting his second example:
public class SharedData
{
internal static string GlobMeta;
internal static int GlobValue;
public SharedData(string meta, int value)
{
GlobMeta = meta;
GlobValue = value;
}
public SharedData(){}
}
public class DerivedData: SharedData
{
public DerivedData() : base()
{
Console.WriteLine("Shared meta = {0}, Shared Value = {1}", GlobMeta, GlobValue);
}
}
Declaring the static variables as 'internal means they will only be accessible in the scope of 'SharedData and any classes derived from it.
Related
I'm trying to make properties for mutable objects. Is this a problem with Auto-properties? For example, the following code would allow for unwanted manipulation of the mutable object. How would I avoid this?
public class Mutable{
public int Value { get; set; }
}
public class ClassWithMutable{
public Mutable Object { get; }
public ClassWithMutable(){
this.mutable = new Mutable();
this.mutable.Value = 0;
}
}
public class Demo{
public static void Main(String[] args){
ClassWithMutable test = new ClassWithMutable();
Mutable o = test.Object;
o.Value = 1;
}
}
You could use an interface that only exposes the get of the properties, and a private class that implements it.
public interface IImmutable {
int Value { get; }
}
public class ClassWithImmutable{
private Mutable _object;
public IImmutable Object { get { return _object; } }
public ClassWithImmutable(){
this._object = new Mutable();
this._object.Value = 0;
}
private class Mutable : IImmutable {
public int Value { get; set; }
}
}
public class Demo{
public static void Main(String[] args){
ClassWithImmutable test = new ClassWithImmutable();
IImmutable o = test.Object;
o.Value = 1; // fails
}
}
I'm trying to understand the intent of your question rather than your question, and I'm coming up a little short. However, I think I came up with something.
You can "mask" your mutable object under a read-only interface.
public class ClassWithMutable
{
public IImumutable Mutable { get { return _mutable; } }
private Mutable _mutable;
public ClassWithMutable()
{
_mutable = new Mutable()
{
Value = 1
};
}
}
public interface IImumutable
{
int Value { get; }
}
public class Mutable : IImumutable
{
public int Value { get; set; }
}
As long as your ClassWithMutable instance exposes the Mutable instance as an Immutable then the consumer can't easily change it. (I emphasize easily, because there's pretty much always a way that you can change it. It just depends on how hard you want to work.)
I have the following base class:
public class Base
{
public string LogicalName { get; set; }
public int NumberOfChars { get; set; }
public Base()
{
}
public Base(string logicalName, int numberOfChars)
{
LogicalName = logicalName;
NumberOfChars = numberOfChars;
}
}
and the following derived classes:
public class Derived1 : Base
{
public const string EntityLogicalName = "Name1";
public const int EntityNumberOfChars = 30;
public Derived1() : base(EntityLogicalName, EntityNumberOfChars)
{
}
}
public class Derived2 : Base
{
public const string EntityLogicalName = "Name2";
public const int EntityNumberOfChars = 50;
public Derived2()
: base(EntityLogicalName, EntityNumberOfChars)
{
}
}
and I also have this function that is provided by a service:
public IEnumerable<T> GetEntities<T>(string entityName, int numberOfChars) where T : Base
{
//Some code to get the entities
}
My problem is how can I call this function generically? I want to call it with something that looks like this:
public void TestEntities<T>() where T : Base
{
var entities = GetEntities<T>(T.EntityLogicalName, T.EntityNumberOfChars);
//some other code to test the entities
}
This of course doesn't work because at this point T is not known. How can I accomplish something similar to this? EntityLogicalName and EntityNumberOfChars are characteristics that all Base derived classes have and they never change for each derived class. Can I get them from the Base class without instantiating objects or some other way that I am not seeing?
Replace constants with getter abstract properties
public abstract class Base
{
public abstract string LogicalName { get; }
public abstract int NumberOfChars { get; }
public Base()
{
}
}
public class Derived1 : Base
{
public string LogicalName { get { return "Name1"; } }
public int NumberOfChars { get { return 30; } }
public Derived1() : base()
{
}
}
Also, you will be able to put some logic into overriden getter, e.g. :
...
public string LogicalName { get { return this.EntityMap.Name; } }
...
UPDATE: The fact that you do not want to instantiate object from class but want to be able to get that string in a strongly typed manner can be handled in one more way. It is totally separate from answer above ( Since you can't override static props in c#). Consider the following code. We are adding one more class here, but LocatorInner can be a member of BaseClass. We are using this approach a lot in several existing apps.:
public class Locator
{
public static class LocatorInner<T> where T : BaseClass
{
public static string Name { get; set; }
}
public static string GetName<T>() where T : BaseClass
{
return LocatorInner<T>.Name;
}
public static void SetName<T>(string name) where T : BaseClass
{
LocatorInner<T>.Name = name;
}
}
public class BaseClass
{
}
public class DerivedClass: BaseClass
{
static DerivedClass()
{
Locator.LocatorInner<DerivedClass>.Name = "me";
}
}
public class TestClass<T> where T : BaseClass
{
public void Method()
{
var name = Locator.GetName<T>();
}
}
IMHO, I believe using constants here is a bad design decision.
You can either solve the issue using #vittore approach, but for me it sounds like you should use meta-programming with attributes if you're looking to get data from the T generic argument
For example, what about:
public class LogicalNameAttribute : Attribute
{
public LogicalNameAttribute(string name)
{
Name = name;
}
public string Name { get; private set; }
}
public class NumberOfCharsAttribute : Attribute
{
public NumberOfCharsAttribute (int number)
{
Number = number;
}
public string Number { get; private set; }
}
[LogicalName("Name1"), NumberOfChars(30)]
public class Derived1 : Base
{
public Derived1() : base()
{
}
}
Now your service method can extract attribute metadata as follows:
public void TestEntities<T>() where T : Base
{
LogicalNameAttribute logicalNameAttr = typeof(T).GetCustomAttribute<LogicalNameAttribute>();
NumberOfCharsAttribute numberOfCharsAttr = typeof(T).GetCustomAttribute<NumberOfCharsAttribute >();
Contract.Assert(logicalNameAttr != null);
Contract.Assert(numberOfCharsAttr != null);
string logicalName = logicalNameAttr.Name;
int numberOfChars = numberOfCharsAttr.Number;
// Other stuff
}
There's a performance penalty because you need to use reflection to get attributes applied to T, but you gain the flexibility of not forcing derived classes to provide this static info.
As #vittore mentioned, move the properties to base,pass the hard coded values from derived and in creation use just defautl(T)
public IEnumerable<T> GetEntities<T>(string entityName, int numberOfChars) where T : Base
{
yield return default(T); //Is its always class use new constraint and return new T();
}
I have 3 classes MetaA, MetaB and MetaC. Each have a number of properties.
There are certain situations where it would be nice to just have one class that contains the properties of all three Meta classes, called for example, MetaComposite. In the composite class, I have tried creating and instance of each MetaA, B and C in the hope that I could access the properties like so:
Meta Composite mc = new MetaComposite();
mc.MetaA.Property1 = "Hello";
Since C# does not allow multiple inheritance, what is the best way of making a class that is a composite of other classes? I could put fields and write getters and setters in the composite class to pass on the property values, but this would be a lot of duplicated code.
What is the correct approach here?
How about creating interfaces for all three Meta classes and have the MetaComposite class implement all three of these interfaces. The MetaComposite class can instantiated the correct Meta class and call it to execute the desired property.
Here is an example:
public interface IMeta1
{
int Metaproperty1 {get; set;}
}
public interface IMeta2
{
int Metaproperty2 {get; set;}
}
public interface IMeta3
{
int Metaproperty3 {get; set;}
}
public class MetaComposite : IMeta1, IMeta2, IMeta3
{
private readonly Meta1 _meta1;
private readonly Meta2 _meta2;
private readonly Meta3 _meta3;
public MetaComposite()
{
_meta1 = new Meta1();
_meta2 = new Meta2();
_meta3 = new Meta3();
}
public int Property1
{
get { return _meta1.Property1; }
set { _meta1.Property1 = value; }
}
public int Property2
{
get { return _meta2.Property2; }
set { _meta2.Property2 = value; }
}
public int Property3
{
get { return _meta3.Property3; }
set { _meta3.Property3 = value; }
}
}
What is the reason to have all properties on class level?
Why not simply use exactly what you wrote?
class MetaComposite
{
public MetaAClass MetaA { get; private set; }
public MetaBClass MetaB { get; private set; }
public MetaCClass MetaC { get; private set; }
public MetaComposite()
{
MetaA = new MetaAClass();
MetaB = new MetaBClass();
MetaC = new MetaCClass();
}
}
public void Main()
{
var composite = new MetaComposite();
composite.MetaA.Field1 = 1;
composite.MetaB.Field2 = '2';
composite.MetaC.Field3 = new MetaDClass();
}
The target is to have a variable with a Unit property, which could be accessed by e.g.:
Params MyParams;
MyParams.Diae = 100.0;
MyParams.Diae.Unit = "kg";
Ideally, the variable Diae is a member of Class Params and should Inherit the Unit property from a class IParameter:
internal class IParameter
{
string unit;
internal string Unit { get; set; }
internal IParameter()
{
unit = "";
}
}
How to declare Diae variable? Here is a snippet of a quasi-code of the declaration expected:
namespace SomeCode
{
internal class Params
{
double diae;
internal class Diae:IParameter
{
get { return diae; }
set { diae = value; }
}
}
}
You can't do exactly what you want -- you can't add extra properties to an existing type like double, so you'll have to make Diae return a separate class. Something like this:
internal class ParamWithUnit
{
public string Unit { get; set; }
public double Value { get; set; }
}
internal class Params
{
private ParamWithUnit diae = new ParamWithUnit();
public ParamWithUnit Diae
{
get { return this.diae; }
}
}
Then you can do:
Params MyParams = new Params();
MyParams.Diae.Value = 100.0;
MyParams.Diae.Unit = "kg";
You won't [want to] be able to assign a double to Diae while still allowing it to have a property Unit. (You could hack around this through implicit conversions or something like that, but I would discourage you from doing so.)
The best option would be to create a class such as Measurement that will have both a Value and a Unit property:
public class Measurement
{
public double Value {get;set;}
public string Unit {get;set;}
}
Then Diae can be of that type:
internal class Params
{
public Measurement Diae {get;private set}
public Params()
{
Diae = new Measurement();
}
}
Now you can do:
Params MyParams = new Params();
MyParams.Diae.Value = 100.0;
MyParams.Diae.Unit = "kg";
I'm wondering about what's the way to go, if I need to publicate data-interfaces but want to use them internal with extended calculated properties. To make it clearer:
// The public interface
public interface IData
{
int Property { get; }
}
// The internal interface
internal interface IExtendedData : IData
{
int ExtendedProperty { get; }
}
// The assumed implementation of someone using my interface
public class Data : IData
{
public Data(int a)
{
Property = a;
}
public int Property
{
get;
private set;
}
public override string ToString()
{
return Property.ToString();
}
}
// My implementation
internal class ExtendedData : IExtendedData
{
public ExtendedData(int a)
{
Property = a;
}
public int Property
{
get;
private set;
}
public int ExtendedProperty
{
get
{
return 2 * Property;
}
}
public override string ToString()
{
return Property.ToString() + ExtendedProperty.ToString();
}
}
// publicated by me, for the person who uses my dll
public static class Calculations
{
public static int DoSomeCalculation(IData data, int parameter)
{
// This probably don't work, but maybe shows what I want to do
IExtendedData tempData = (ExtendedData)data;
return tempData.ExtendedProperty * parameter;
}
}
I'm realy frustrated, cause I feel like missing some basical programing skills.
You could solve this problem by implementing ExtendedData as a Wrapper for a class implementing IData
internal class ExtendedData : IExtendedData
{
private IData data;
public ExtendedData(IData data)
{
this.data = data;
}
public int Property
{
get { return data.Property; }
private set { data.Property = value; }
}
public int ExtendedProperty
{
get
{
return 2 * Property;
}
}
}
and use this in DoSomeCalculation like
IExtendedData tempData = new ExtendedData(data);
ExtendedData could inherit from Data:
class ExtendedData : Data
{...}
And for creation of a Data object you add a factory like so:
public class DataFactory
{
public IData CreateData()
{
return new ExtendedData();
}
}
User have to create all its Data objects by this factory. You can ensure it by making Data's constructor internal.
In your DLL you can then cast to ExtendedData.