Collection of generic types [duplicate] - c#

This question already has answers here:
Collection of generic types
(10 answers)
Closed 7 years ago.
I have an object (form) which contains a collection (.Fields) which I want to contain instances of a generic class (FormField).
The FormField, simply, is defined as such:
public class FormField<T>
{
private Form Form;
public T Value { get; set; }
public string Name { get; set; }
public void Process()
{
// do something
}
public FormField(Form form, string name, T value)
{
this.Name = name;
this.Value = value;
this.Form = form;
}
}
This allows me to have FormField, FormField etc. and that part works great.
What I want is a collection of "Formfields" regardless of the type, but I am forced into defining a type (it seems) such as:
public class Form
{
string Code { get; set; }
string Title { get; set; }
int Year { get; set; }
Guid ClientID { get; set; }
ICollection<FormField<int>> Fields { get; set; }
}
What, I think, I want is an interface that allows me to abstract the type information and thus type the collection as instances of (for exxample) IFormField not FormField<>
But I can't see how to define this without strongly typing the collection in the interface...
Any help (including any alternative solutions!) would be greatly appreciated!
Thanks, Ben

Here's some code to complete Jon's answer:
public interface IFormField
{
string Name { get; set; }
object Value { get; set; }
}
public class FormField<T> : IFormField
{
private Form Form;
public T Value { get; set; }
public string Name { get; set; }
public void Process()
{
// do something
}
public FormField(Form form, string name, T value)
{
this.Name = name;
this.Value = value;
this.Form = form;
}
// Explicit implementation of IFormField.Value
object IFormField.Value
{
get { return this.Value; }
set { this.Value = (T)value; }
}
}
And in your form:
ICollection<IFormField> Fields { get; set; }

Create a non-generic interface or base class, which probably includes everything FormField does except the type-specific bits. Then you can have an ICollection<IFormField>. Obviously you won't be able to use this in a strongly-typed way, in terms of the type of field being used - but you can use all the non-type-specific bits of it (e.g. the name and the form).

Another option (an alternative to Jon's answer) is to apply the adapter pattern, which can be useful when:
you are unable to modify the type, and can thus not define a base-type for it.
or, there is a need to expose 'type-specific bits' (as Jon put it).
When you want to expose type-specific bits, you effectively have to create a non-generic wrapper. A short example:
class NonGenericWrapper<T> : IAdaptor
{
private readonly Adaptee<T> _adaptee;
public NonGenericWrapper(Adaptee<T> adaptee)
{
_adaptee = adaptee;
}
public object Value
{
get { return _adaptee.Value; }
set { _adaptee.Value = (T) value; }
}
}
Implementing this non-generic behavior in a base-type would effectively break the Liskov substitution principle, which is why I prefer the wrapper approach as I also argue in my blog post.

Related

Is there a possibility to somehow overcome limitations of using generics in interface? (without boxing/unboxing)

I'm trying to create set of interfaces that will be used in several classes. But I have troubles with setting them properly. I want to keep them generic.
I tried to get around this using dynamic type and object type without success. Maybe this will be clear with attached those interfaces below:
In code below type T is unknown. I cannot specify it because each IDeviceParameter will be different type. And number of parameters is not fixed, so I want to simply add all available IParameters to list. Only solution that came into my mind is to use some sort of boxing/unboxing (for example cast int to object and vice versa) or use dynamic. Or to totally change those interfaces. Thanks you in advance for any advises.
public interface IDevice : IDisposable
{
string Name { get; }
bool Close();
Guid DeviceGuid { get; }
IList<IDeviceParameter<T>>AvailableParameters { get; }
IList<IDeviceCommand> AvailableCommands { get; }
}
public interface IDeviceParameter<T>
{
event EventHandler<IDeviceParameter<T>> ParameterValueChanged;
event EventHandler<Exception> ParameterNotSet;
string ParameterName { get; }
string ParameterValue { get; }
string ParameterUnit { get; }
bool IsReadOnly { get; }
T Parameter { get; }
void SetParameter(T value);
}
Below is some concrete implementation (not working because of error like "Cannot convert from type Object to type int") :
public class Device : IDevice
{
public int _setableParameter1 = 1;
public string _setableParameter2 = "2";
private Guid _guid;
private string _name;
private List<IDeviceCommand> _cmdList = new List<IDeviceCommand>();
private List<IDeviceParameter<object>> _paramList = new List<IDeviceParameter<object>>();
public Device()
{
IDeviceParameter<int> setableParameter1 = DeviceParameterFactory.Factory<int>.CreateParameter("SomeParameter1", "V", delegate { throw new DeviceParameterFactory.ParametersNotSetException("SomeParameter1"); }, ref _setableParameter1);
IDeviceParameter<string> setableParameter2 = DeviceParameterFactory.Factory<string>.CreateParameter("SomeParameter2", "V", delegate { throw new DeviceParameterFactory.ParametersNotSetException("SomeParameter2"); }, ref _setableParameter2);
_cmdList.Add(setableParameter1);
_cmdList.Add(setableParameter2);
_guid = Guid.NewGuid();
_name = "Device" + DateTime.Now.Millisecond;
}
Some explanation: factory class returns IDeviceParameter, and those types for sure are known at compilation time because they are explictly set.
If you have something of type IDeviceParameter<string> and something of IDeviceParameter<int> then there is no way to make that into an IDeviceParameter<object> without doing new IDeviceParameter<object>() somewhere. This is because they are just entirely different interfaces to the program. For the compiler you might as well have created classes named IIntDeviceParameter and IStringDeviceParameter.
If these classes share a similar interface, then you will need to explicitly state this, i.e. you would need to make an interface IUnknownTypeDeviceParameter, but you cannot put the fields or methods that use T in their type definition in there. So you could do this:
public interface IUnknownTypeDeviceParameter
{
event EventHandler<Exception> ParameterNotSet;
string ParameterName { get; }
string ParameterValue { get; }
string ParameterUnit { get; }
bool IsReadOnly { get; }
}
public interface IDeviceParameter<T> : IUnknownTypeDeviceParameter
{
event EventHandler<IDeviceParameter<T>> ParameterValueChanged;
event EventHandler<Exception> ParameterNotSet;
string ParameterName { get; }
string ParameterValue { get; }
string ParameterUnit { get; }
bool IsReadOnly { get; }
T Parameter { get; }
void SetParameter(T value);
}
If you would like to use one of the functions in IDeviceParameter<T> on an IUnknownTypeDeviceParameter you would need to cast it back to an IDeviceParameter<T>.

C# Using base or this in inherited get

I am having trouble understanding the proper use of base and this within an inherited get method. I have an interface IMatchModel:
public interface IMatchModel
{
int TypeId { get; }
DateTime DataDate { get; set; }
string TypeName { get; set; }
}
And a base model class TradeModel:
public class TradeModel
{
public long TradeId { get; set; }
public DateTime DataDate { get; set; }
public string TradeName { get; set; }
}
Then I have a class that inherits from TradeModel and implements IMatchModel. I am currently using the following method:
public class TradeMatchModel : TradeModel, IMatchModel
{
public int TypeId { get { return 1; } }
public string TypeName
{
get
{
return base.TradeName;
}
set
{
base.TradeName = value;
}
}
}
The TradeModel class is used within a function that operates on all of its attributes. IMatchModel is used in a function that only needs the attributes contained in the interface. The code works properly, but I still feel like I don't quite understand if it is best to be using base over this. Is the use of base in this context incorrect?
The only time you need to use base is when you are inside a overridden virtual method and you need to call the base implementation of the method you are currently overriding. All other times you can use this..
Also this. is generally not needed unless you have a name conflict between a field or property in the class and a name of a variable or a parameter. 99% of the time you can just leave off the this. and do return TradeName;

Why create public wrappers to private members in a class?

I've always had this question, but I've blindly followed on so far.
This is from a piece of example code:
Why do this:
public class EmployeeInfo
{
int _EmpNo;
public virtual int EmpNo
{
get { return _EmpNo; }
set { _EmpNo = value; }
}
string _EmpName;
public virtual string EmpName
{
get { return _EmpName; }
set { _EmpName = value; }
}
}
when there's nothing additional, such as calculations or validations, being done during getting/setting?
Will this suffice?
public class EmployeeInfo
{
public int EmpNo { get; set; }
public string EmpName { get; set; }
}
Also, why virtual for the public member wrappers?
Why do this?
There's really no reason to since the addition of auto-implemented properties in C# 3.0. It could be legacy code that hasn't been changed, old habits, or keeping consistency with pre-C# 3 code.
Will this suffice?
No - you've converted the virtual properties to non-virtual. So they are not completely equivalent.
The equivalent would be
public class EmployeeInfo
{
public virtual int EmpNo { get; set; }
public virtual string EmpName { get; set; }
}
Also, why virtual for the public member wrappers?
So that a derived class can override the logic for the properties - to add validation, change notification, etc.
When does the shortened form actually have an impact?
When the backing fields are referenced by the internal code of the class (which can be detected at compile-time), or when they're accessed by reflection (which cannot be detected until run-time, or via static code analysis).
An "auto-implemented" property actually gets a backing field created by the compiler, so in that sense they're equivalent if the only place the backing field is referenced is within the property code.
You have two questions. First is changing properties to auto implemented properties, they should be equal, but you removed virtual keyword, that makes them different.
So, what is virtual. That keyword will allow derived classes to override the get/set for the said property.
See: virtual C#
The virtual keyword is used to modify a method, property, indexer, or
event declaration and allow for it to be overridden in a derived
class.
Your class with auto-implemented properties would be equal if you have:
public class EmployeeInfo
{
public virtual int EmpNo { get; set; }
public virtual string EmpName { get; set; }
}
Later you can override a property and leave the other to maintain the parent behaviour, like:
public class ManagerInfo : EmployeeInfo
{
private int _EmpNo;
public override int EmpNo
{
get { return _EmpNo; }
set
{
if (value < 100) throw new Exception("EmpNo for manager must be greater than 100");
_EmpNo = value;
}
}
}
Depends if you want to see the field publicly or not,
if your only going to use the field inside the declaring class then you don't need to wrap it in a property, its only if you need to expose it publicly or down the inheritance tree that you should have the property
public string EmpName { get; set; }
is just a compiler short cut to
private string _EmpName;
public string EmpName {
get{ return _EmpName;}
set(_EmpName = value; }
}
they are functionally identical.
However there are things that the short cut wont let you do, for example you want to raise an event when the property changes.
there there is also your use of Virtual which is an inheritance modifier
Virtual instructs the code that it needs to look DOWN the inheritance tree for a newer implementation.
so in
class A
{
public string Data
{
get{return "A";}
}
public virtual string VData
{
get{return "A";}
}
}
class B:A
{
public new string Data
{
get{return "B";}
}
public override string VData
{
get{return "B";}
}
}
then if you do
A obj = new B();
obj.Data; //return A
obj.VData; //return B
It looks like the code in this form:
$type _$var;
public virtual $type $var
{
get { return _$var; }
set { _$var = value; }
}
Was generated using a tool, template or snippet. As habits hardly ever change and tools, templates and snippets hardly ever get updated, I guess they were created before auto-implemented properties (public $type $var { get; set; }) were introduced to the C# language.
For the code you show, it's perfectly valid to have the equivalent:
public virtual $type $var { get; set; }
As you can override the auto-implemented property and add a backing field, validation and whatever when required.
The expanded form is the traditional way to do it:
public class MyClass
{
int _myInt;
virtual public int MyProperty
{
get
{
return _myInt;
}
set
{
_myInt = value;
}
}
}
However, the shorter form is called "auto properties", introduced in C# 3.0.
public class MyClass
{
virtual public int MyProperty { get; set; }
}
These code blocks are equivalent. This is a good practice for keeping your code concise.
One thing to consider: You aren't able to make the internal variable protected with auto properties, so if you create a derived class and override your property, you'll need to use base.MyProperty to access it, or use the expanded form.

Handling different representations method [duplicate]

This question already has answers here:
C# generic "where constraint" with "any generic type" definition?
(2 answers)
Closed 9 years ago.
i have a basic DataTag class defined in this way:
public abstract class DataTag<TRaw, TVal>
{
public abstract TVal Value { get; }
public TRaw RawValue { get; set; }
public string Name { get; private set; }
public string Desc { get; private set; }
}
where TRaw is raw data taken from a device, while TVal is the "formatted" value.
So i may have 2 tags from same device:
DataTag t1 = DataTag.Create<ushort,int>();
DataTag t2 = DataTag.Create<ushort[],float()>;
Now i have a class which should contain a list of generic tags
private IEnumerable<DataTag<?,?> _tags();
Of course C# will not accept different kind of generic in the same list, but this is what i would like to achieve. Any tip for that?
One common approach is to declare a non-generic base class. It won't give you strongly-typed access to the data of course, but you can potentially get a plain object version, and the name/description.
public abstract class DataTag
{
public string Name { get; private set; }
public string Description { get; private set; }
public abstract object WeakValue { get; }
public abstract object WeakRawValue { get; }
}
public abstract class DataTag<TRaw, TVal> : DataTag
{
public abstract TVal Value { get; }
public TRaw RawValue { get; set; }
public override object WeakValue { get { return Value; } }
public override object WeakRawValue { get { return RawValue; } }
}
Then your list is just an IEnumerable<DataTag>.
Notes:
I've given different names for the "weakly typed" properties. You could use Value and RawValue, then redeclare them (with new) in the generic type, but that's a pain in the neck in other ways. Avoid the naming collision if you can.
I've only provided a getter for WeakRawValue - you could provide a setter as well, and cast within the generic type, but that feels ugly to me. Heck, I would personally try to get rid of the setters entirely, and pass the values in as constructor arguments, making the type closer to immutable. (It's not going to be "properly" immutable if either of the generic type arguments is itself a mutable type, but it's better than nothing...)

How to create and set a polymorphic property?

I want to create a class that can take different types of value in a property. I am trying to do this using polymorphism, but I am not still learning how to do this properly, hence my request for advice.
I have a base class and two classes that inherit from it:
public abstract class BaseClass
{
public string Name { get; set; }
public Unit Unit { get; set; }
}
public class DerivedClassFloat : BaseClass
{
public float Value { get; set; }
public override string ToString()
{
return Value.ToString();
}
}
public class DerivedClassString : BaseClass
{
public string Value { get; set; }
public override string ToString()
{
return Value;
}
}
All is good, I can create a List and add different specialized subclasses. My problem comes when I need change the values of the items in my list:
foreach (var item in ListOfBaseClasses)
{
if(item is DerivedClassFloat)
((DerivedClassFloat) item).Value = float.NaN;
if (item is DerivedClassString)
((DerivedClassString) item).Value = string.Empty;
}
According to what I have read, that looks like a code smell. Is there a better way to access the value property of my derived classes based on the type I am trying to assign?
What about when you want to create the right subclass based on the value?
BaseClass newClass = null;
if (phenotype is DerivedClassFloat)
newClass = new DerivedClassFloat(){Value = 12.2};
if (phenotype is DerivedClassString)
newClass = new DerivedClassString(){Value = "Hello"};
I read about overriding virtual methods, but that works if I want to process the value, not to add or change it … maybe I am missing something?
I should make this more concrete, my apologies, I am not used to post question in this great site.
I need a property that is made of a list of attributes. Each attribute has a name and a value, but the value can be of different types. For example:
public class Organism
{
public string Name { get; set; }
public List<Attribute> Attributes { get; set; }
}
public class Attribute
{
public string AttributeName { get; set; }
public object AttributeValue { get; set; }
}
For a given organism I can have several attributes holding different value types. I wanted to avoid using the object type so that I don’t have to cast to the right type. I though property polymorphism was the solution to handle this case elegantly, but then I found myself using If ..Then which didn’t seem too different from casting in the first place.
If in your particular case you want to reset Value, you can define an abstract ResetValue method in the base class, which will be implemented by the derives classes.
As for your second case, you should check out Creational Design Patterns, and specifically the Factory and Prototype design patterns.
You can use generics to define the type and the implementing subclass will set the Value type to the type constraint:
public abstract class BaseClass<T>
{
public string Name { get; set; }
public Unit Unit { get; set; }
public T Value { get; set; }
public override string ToString()
{
return Value.ToString();
}
}
public class DerivedFloat : BaseClass<float> {}
public class DerivedString : BaseClass<string> {}
You can use Generics for this particular case:
public abstract class BaseClass<T>
{
public string Name { get; set; }
public Unit Unit { get; set; }
public T Value { get; set; }
}
public class DerivedClassFloat : BaseClass<float>
{
public override string ToString()
{
return Value.ToString();
}
}
public class DerivedClassString : BaseClass<string>
{
public override string ToString()
{
return Value;
}
}
Polymorphic behaviour works on abstraction. Based on what your trying to do, you can reduce code smell to moving as much of your variability in code to base classess.
i would suggest is instead of property write method like as follows. You can something like as follows.
public void setValue(string val, Type type);//move this to your base class
Class MyValue{
private string strVal;
private int intVal;
//constructor
MyValue(string val, Type type){
//check the type enum here and set the values accordingly
}
}
then when set values
foreach (var item in ListOfBaseClasses)
{
item.setValue = MyValue("",Type.INT);
}
I'm not quite sure what you are trying to achieve with this approach - the Value properties are not of the same type, there is also no Value property on the base class which suggests that other types derived from the base class might not have it at all.
If all of your classes require a Value property, then maybe it should be of the most general type object - you could put it onto the base class, but that would require casting the values in the derived classes.
But then you could have a NullObject to represent an absence of value that you could assign to the Value property for every derived class.
You can use the abstract factory pattern. Consider this example:
// Base class
class Button
{
protected Button()
{
}
public string Name { get; set; }
}
// Factory interface
public interface ButtonFactory
{
Button CreateButton();
}
// And the concrete classes
class WindowsButton : Button
{
// ...
}
class WindowsButtonFactory : ButtonFactory
{
public Button CreateButton()
{
return new WindowsButton();
}
}
class MacButton : Button
{
// ...
}
class MacButtonFactory : ButtonFactory
{
public Button CreateButton()
{
return new MacButton();
}
}
Furthermore, you can combine the abstract factory pattern with the strategy pattern to encapsulate the custom behaviors that change with type.

Categories

Resources