The following is my code
Common
public abstract class DataFieldBase
{
public DataFieldCollection<DataFieldBase> Parent;
public string FieldName;
protected object BaseValue;
public DataFieldBase(string fieldName, object value)
{
this.FieldName = fieldName;
this.BaseValue = value;
}
}
public class StringField : DataFieldBase
{
public StringField() : base("StringField", "Test") { }
public object Value
{
get { return this.BaseValue; }
set { this.BaseValue = value; }
}
}
public class ReadOnlyField : DataFieldBase
{
public ReadOnlyField() : base("ReadOnlyField", System.Guid.NewGuid()) { }
public object Value
{
get { return this.BaseValue; }
}
Sample A
I cannot assign a parent(DataFieldCollection) to child
Compile error (Cannot implicitly convert type 'ConsoleApplication1.DataFieldCollection<T>' to 'ConsoleApplication1.DataFieldCollection<ConsoleApplication1.DataFieldBase>')
class Program
{
static void Main(string[] args)
{
DataFieldCollection<DataFieldBase> dataFields = new DataFieldCollection<DataFieldBase>();
StringField stringField = new StringField();
ReadOnlyField readOnlyField = new ReadOnlyField();
dataFields.Add(stringField);
dataFields.Add(readOnlyField);
}
}
public class DataFieldCollection<T> where T : DataFieldBase
{
private Dictionary<string, T> _collection = new Dictionary<string, T>();
public DataFieldCollection() { }
public void Add(T field)
{
field.Parent = this;
this._collection.Add(field.FieldName, field);
}
public T Get(string fieldName)
{
return this._collection[fieldName];
}
}
Sample B
I can compile.
class Program
{
static void Main(string[] args)
{
DataFieldCollection<DataFieldBase> dataFields = new DataFieldCollection<DataFieldBase>();
StringField stringField = new StringField();
ReadOnlyField readOnlyField = new ReadOnlyField();
stringField.Parent = dataFields;
dataFields.Add(stringField);
readOnlyField.Parent = dataFields;
dataFields.Add(readOnlyField);
}
}
public class DataFieldCollection<T> where T : DataFieldBase
{
private Dictionary<string, T> _collection = new Dictionary<string, T>();
public DataFieldCollection() { }
public void Add(T field)
{
this._collection.Add(field.FieldName, field);
}
public T Get(string fieldName)
{
return this._collection[fieldName];
}
}
Why Sample A cannot
Please help me

Generic Bug or Limitation or By Design?
Yel
It can solve my problem in your approach 1 but it will lose parent default interface when implement. For example.
public interface IParent
{
string ID{ get;}
}
public class DataFieldCollection<T> : IParent where T : DataFieldBase {
public DataFieldCollection(){}
public void Add(T Field){}
public string ID
{
get { return "ABC"; }
}
}
static void Main(string[] args)
{
......
dataFields.Add(stringField);
((DataFieldCollection<DataFieldBase ) stringField.Parent).Add(...)
}
It will casting again...that you know one of the benefit of generic is reducing to casting
And your approach 2 that it cannot be compiled
(The type 'T' must be convertible to 'ConsoleApplication1.DataFieldBase<T>' in order to use it as parameter 'T' in the generic type or method 'ConsoleApplication1.DataFieldCollection<T>')
DMOORE
Thank you for you repley
I think this approach not suitable for me. In your approach that I will lose dirrect reference. For example If DataFieldCollection add a Readonly field the memberwiseClone will clone this field
dataFields.ReadOnly=false;
dataFields.Add(AField);
Now AField.Parent.ReadOnly is false;
If I changed dataFields.ReadOnly=true, the AField.Parent.ReadOnly still is false;
If this is not a bug I think generic is not useful for me that I think this is general design structure. In this design child added into the collection that the collection will notify which parent is collection. If sample A cannot do that I will give up generic approach in this design. I will change the design to the following
public class DataFieldCollection
{
private Dictionary<string, DataFieldBase> _collection = new Dictionary<string, DataFieldBase>();
public DataFieldCollection() { }
public void Add(DataFieldBase field)
{
this._collection.Add(field.FieldName, field);
}
public DataFieldBase Get(string fieldName)
{
return this._collection[fieldName];
}
}
In this design I will alway casting when get it for example
static void Main(string[] args)
{
DataFieldCollection dataFields = new DataFieldCollection();
StringField stringField = new StringField();
dataFields.Add(stringField);
stringField = (stringField) dataFields.Get(stringField.FieldName);
}
neuralsea8
public interface IParent {...}
public class DataFieldCollection<T> : IParent where T : DataFieldBase {...}
public abstract class DataFieldBase
{
public IParent Parent;
...
}
OR
public abstract class DataFieldBase<T>
{
public DataFieldCollection<T> Parent;
...
}
aschreiber2
public class DataFieldCollection<T1,T2>
where T1 : DataFieldBase<T2>
{...}
public abstract class DataFieldBase<T>
{
public DataFieldCollection<DataFieldBase<T>,T> Parent ;
...
}
Graham Parker
public void Add(T field)
{
field.Parent = (DataFieldCollection <DataFieldBase> ) this.MemberwiseClone() ;
this._collection.Add(field.FieldName, field) ;
}
if u cast like this, it works well..
so its not bug.. try like this