Is it possible to add different type of generic objects to a list?. As below.
public class ValuePair<T>
{
public string Name { get; set;}
public T Value { get; set;
}
and let say I have all these objects...
ValuePair<string> data1 = new ValuePair<string>();
ValuePair<double> data2 = new ValuePair<double>();
ValuePair<int> data3 = new ValuePair<int>();
I would like to hold these objects in a generic list.such as
List<ValuePair> list = new List<ValuePair>();
list.Add(data1);
list.Add(data2);
list.Add(data3);
Is it possible?
In general, you'd have to either use a List<object> or create a non-generic base class, e.g.
public abstract class ValuePair
{
public string Name { get; set;}
public abstract object RawValue { get; }
}
public class ValuePair<T> : ValuePair
{
public T Value { get; set; }
public object RawValue { get { return Value; } }
}
Then you can have a List<ValuePair>.
Now, there is one exception to this: covariant/contravariant types in C# 4. For example, you can write:
var streamSequenceList = new List<IEnumerable<Stream>>();
IEnumerable<MemoryStream> memoryStreams = null; // For simplicity
IEnumerable<NetworkStream> networkStreams = null; // For simplicity
IEnumerable<Stream> streams = null; // For simplicity
streamSequenceList.Add(memoryStreams);
streamSequenceList.Add(networkStreams);
streamSequenceList.Add(streams);
This isn't applicable in your case because:
You're using a generic class, not an interface
You couldn't change it into a generic covariant interface because you've got T going "in" and "out" of the API
You're using value types as type arguments, and those don't work with generic variable (so an IEnumerable<int> isn't an IEnumerable<object>)
Not unless you have a non-generic base-type ValuePair with ValuePair<T> : ValuePair (it would work for an interface too), or use List<object>. Actually, though, this works reasonably:
public abstract class ValuePair
{
public string Name { get; set; }
public object Value
{
get { return GetValue(); }
set { SetValue(value); }
}
protected abstract object GetValue();
protected abstract void SetValue(object value);
}
public class ValuePair<T> : ValuePair
{
protected override object GetValue() { return Value; }
protected override void SetValue(object value) { Value = (T)value; }
public new T Value { get; set; }
}
No, it is not possible. You could create, in your case, a base class ValuePair from which ValuePair<T> derives. Depends on your purposes.
it's not possible as far as I know.
the line:
List<ValuePair> list = new List<ValuePair>();
you wrote in your sample is not providing a concrete type for T and this is the issue, once you pass it, you can only add object of that specific type.
Related
For starters, I have implemented a workaround to this question based on having multiple private variables store information, and get/set on the affected object.
The scope of this questions is for learning/reference.
Scenario:
I have an interface that manages multiple objects (2 in this example).
interface Imoon
??? SomePropertyName {get;set;}
class Foo : Imoon
public TypeA SomePropertyName {get;set;}
public enumMyType TypeStorage {get;set}
class Bar : Imoon
public TypeB SomePropertyName {get;set;}
public enumMyType TypeStorage {get;set;}
The goal is to be able to reference a list/dictionary/array of objects that may change in type (similiar to a generic). The types don't impact the logic, they are partitioned into separate handlers and managed there.
Once declared, the type of the object does not change.
The Type is the same for all elements within the Enumerable, however may change between different objects.
Example declarations:
Dictionary<string,TypeA> myDictionary;
Dictionary<string,TypeB> myDictionary;
or as a list:
class Foo
List<TypeA> myValues
List<string> myKeys
class Bar
List<TypeB> myValues
List<string> myKeys
If anyone has any suggestions on how to implement this, or suggestions for improvement please let me know :)
For Archiving, I was able to reach the desired result by using a Generic interface as Recommended by johnny5 above.
I've included a example of the solution, and how to implement it with a given type (TypeA), and it could be done on TypeB aswell.
public interface ICollection<T>
{
Dictionary<string,T> TypeDictionary { get; set; }
void AddToDictionary(Dictionary<string,T> Addition
int FileCount { get; }
}
public class TypeACollection : ICollection<TypeA>
{
private Dictionary<string,TypeA> myTypeDictionary = new Dictionary<string, TypeA>();
public void AddToDictionary(Dictionary<string, TypeA> Addition)
{
foreach (var keyValuePair in Addition)
{
TypeDictionary[keyValuePair.Key] = keyValuePair.Value;
}
}
public Dictionary<string, TypeA> GetTypeDictionary()
{
return TypeDictionary;
}
private void ClearDictionary()
{
TypeDictionary.Clear();
}
public Dictionary<string, TypeA> TypeDictionary {
get { return myTypeDictionary; }
set { myTypeDictionary = value; }
}
public int FileCount {get { return TypeDictionary.Keys.Count; }}
}
public class TypeA { }
public class TypeB { }
I've found couple of questions on the same topic here, however I couldn't find what I need. Basically I am searching for this kind of magic:
public class BaseClass
{
public int DerivedТype { get; set; }
}
public class DerivedClass<T> : BaseClass
{
public DerivedClass(T initialValue)
{
DerivedТype = 1;
Property = initialValue;
}
public T Property { get; set; }
}
public class OtherDerivedClass<T> : BaseClass
{
public OtherDerivedClass(T initialValue)
{
DerivedТype = 2;
OtherProperty = initialValue;
}
public T OtherProperty { get; set; }
public int OtherProperty2 { get; set; }
public float OtherProperty { get; set; }
}
public class Program
{
public static void Main()
{
List<BaseClass> baseClassList = new List<BaseClass>();
baseClassList.Add(new DerivedClass<int>(5));
baseClassList.Add(new OtherDerivedClass<float>(6));
foreach (var derived in baseClassList)
{
if (derived.DerivedТype == 1)
{
Console.WriteLine(derived.Property);
}
else if (derived.DerivedТype == 2)
{
Console.WriteLine(derived.OtherProperty);
}
}
}
}
I want a list of BaseClass where I can insert instances of DerivedClass and OtherDerivedClass. So far so good.
DerivedClass and OtherDerivedClass hold different properties so I really have no idea how access them. Also I don't want to use any weired casts. So this part of the code prevents me from building.
if (derived.DerivedТype == 1)
{
Console.WriteLine(derived.Property);
}
else if (derived.DerivedТype == 2)
{
Console.WriteLine(derived.OtherProperty);
}
Any ideas would be appreciated. Thank you in advance!
This looks like a problem that can be solved with polymorphism. I'll make a version of your app that does exactly what you seem to be doing in your example, but if there was more information as to what your target goal is, the solution may be different.
public abstract class BaseClass
{
public abstract void DoSomething();
public abstract void GetData(Dictionary<string,string> container);
}
public class DerivedClass<T> : BaseClass
{
public DerivedClass(T initialValue)
{
Property = initialValue;
}
public T Property { get; set; }
public override void DoSomething()
{
Console.WriteLine(Property);
}
public override void GetData(Dictionary<string,string> container)
{
container.Add(nameof(Property), "{Property}");
}
}
public class OtherDerivedClass<T> : BaseClass
{
public OtherDerivedClass(T initialValue)
{
OtherProperty = initialValue;
}
public T OtherProperty { get; set; }
public int OtherProperty2 { get; set; }
public override void DoSomething()
{
Console.WriteLine(OtherProperty);
}
public override void GetData(Dictionary<string,string> container)
{
container.Add(nameof(OtherProperty), "{OtherProperty}");
container.Add(nameof(OtherProperty2), "{OtherProperty2}");
}
}
Your foreach loop could then be as simple as:
foreach(var derived in baseClassList) derived.DoSomething();
This is the proper way to do something like this using OO. There's no need for the DerivedType integer since the object knows what type of class it is and what to do. This is why one would use polymorphism. It's simple and elegant and OO. Extend or change the DoSomething to be more appropriate for what you're trying to do.
The OP came up with his own solution, but if the goal is to do something with the data that is more meaningful, you could also pass in an object to an abstract method that allows you to do this. I added a GetData method that will return all of the property values as strings. The second type of the dictionary could also be object with the actual value stored in the dictionary.
BaseClass could also be a regular class with a method in it to return an IDictionary of object values with string keys. The method could use reflection to get all property values for whatever class it is the base of. Reflection has much more overhead, though, so is not the most efficient way to do this from an execution standpoint.
The correct way to check if an object is a certain type is to use the is operator such as:
if(derived is DerivedType<int>)
{
// Do what you need to do with the specific object type
}
If you know you're going to cast the object, as pointed out by Adosi, you would use:
var castedValue = derived as DerivedType<int>;
if(castedValue != null)
{
// Do what you need to do with castedValue
}
A null will be returned if the object isn't of type DerivedType<int>. Trying to use (DerivedType)derived would cause an invalid cast exception.
To the best of my knowledge what you want is between impossible and not a good idea. Typechecking is done at compile time. Stuff like Dynamic can move those checks to runtime, but it results in all kinds of issues (functions that take dynamic parameters also return dynamic).
If you got at least C# 7.0, you can at least write a switch for it. Old switch only supported values vs constants for a few select value types and string. But C# 7.0 introduces pattern matching. With that you could even use a is check as part of a case.
Thank you all for the awesome support! I decided to go simple and just use a cast.
public class BaseClass
{
public int DataТype { get; set; }
public object Data { get; set; }
}
public class DataClass<T>
{
public DataClass(T initialValue)
{
Property = initialValue;
}
public T Property { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
List<BaseClass> listBaseClass = new List<BaseClass>();
BaseClass dummy = new BaseClass();
dummy.DataТype = 1;
dummy.Data = new DataClass<int>(50);
listBaseClass.Add(dummy);
if (listBaseClass[0].DataТype == 1)
{
DataClass<int> casted = (DataClass<int>)listBaseClass[0].Data;
Console.WriteLine(casted.Property);
}
}
}
I want to hide the base public property(a data member) in my derived class:
class Program
{
static void Main(string[] args)
{
b obj = new b();
obj.item1 = 4;// should show an error but it doent ???
}
}
class a
{
public int item1 {get; set;}
public int item2 { get; set; }
}
class b : a
{
new private int item1;
}
class c : a
{
}
i have member as public because i want the member to be inherited in c class , but want to hide the member in b class , how can i do this ?
dont i have an option to selectively inherite the variable i want in my base class ??? thats really bad , i think ms should provide us with an option (may be a modifier) to perform this
Edit:
I found the answer myself (i heard lots of them telling this is not possible in c#, but you can kind of do it)
I am including the code in case it is useful
class Program
{
static void Main(string[] args)
{
b obj = new b();
obj.item1 = 4; // shows an error : )
}
}
class a
{
public int item1 { get; set; }
public int item2 { get; set; }
}
class b : a
{
new public static int item1
{
get;
private set;
}
}
I'm going to attempt to explain with examples why this is a bad idea, rather than using cryptic terms.
Your proposal would be to have code that looks like this:
public class Base
{
public int Item1 { get; set; }
public int Item2 { get; set; }
}
public class WithHidden : Base
{
hide Item1; // Assuming some new feature "hide" in C#
}
public class WithoutHidden : Base { }
This would then make the following code invalid:
WithHidden a = new WithHidden();
a.Item1 = 10; // Invalid - cannot access property Item1
int i = a.Item1; // Invalid - cannot access property Item1
And that would be just what you wanted. However, suppose we now have the following code:
Base withHidden = new WithHidden();
Base withoutHidden = new WithoutHidden();
SetItem1(withHidden);
SetItem1(withoutHidden);
public void SetItem1(Base base)
{
base.Item1 = 10;
}
The compiler doesn't know what runtime type the argument base in SetItem1 will be, only that it is at least of type Base (or some type derived from Base, but it can't tell which -- it may be obvious looking at the code snippet, but more complex scenarios make it practically impossible).
So the compiler will not, in a large percentage of the cases, be able to give a compiler error that Item1 is in fact inaccessible. So that leaves the possibility of a runtime check. When you try and set Item1 on an object which is in fact of type WithHidden it would throw an exception.
Now accessing any member, any property on any non-sealed class (which is most of them) may throw an exception because it was actually a derived class which hid the member. Any library which exposes any non-sealed types would have to write defensive code when accessing any member just because someone may have hidden it.
A potential solution to this is to write the feature such that only members which declare themselves hideable can be hidden. The compiler would then disallow any access to the hidden member on variables of that type (compile time), and also include runtime checks so that a FieldAccessException is thrown if it is cast to the base type and tried to be accessed from that (runtime).
But even if the C# developers did go to the huge trouble and expense of this feature (remember, features are expensive, especially in language design) defensive code still has to be written to avoid the problems of potential FieldAccessExceptions being thrown, so what advantage over reorganising your inheritance hierarchy have you gained? With the new member hiding feature there would be a huge number of potential places for bugs to creep into your application and libraries, increasing development and testing time.
What you want to do goes directly against the grain of OO, you can't 'unpublish' members as this violates the substitution principle. You have to refactor this into something else.
Vadim's response reminded me of how MS achieve this in the Framework in certain places. The general strategy is to hide the member from Intellisense using the EditorBrowsable attribute. (N.B. This only hides it if it is in another assembly) Whilst it does not stop anyone from using the attribute, and they can see it if they cast to the base type (see my previous explination) it makes it far less discoverable as it doesn't appear in Intellisense and keeps the interface of the class clean.
It should be used sparingly though, only when other options like restructuring the inheritance hierarchy would make it a lot more complex. It's a last resort rather than the first solution to think of.
If you use an interface instead of a base class for defining the property, you could implement the property explicitly. The would require an explicit cast to the interface to use the property.
public interface IMyInterface
{
string Name { get; set; }
}
public class MyClass : IMyInterface
{
string IMyInterface.Name { get; set; }
}
You can find more out here.
The only thing I can think of is to make item1 virtual in class a:
class a
{
public virtual int item1 { get; set; }
public int item2 { get; set; }
}
and then override it in class b but throw an exception in getter and setter. Also if this property is used in a visual designer you can use Browsable attribute to not display.
class b : a
{
[Browsable(false)]
public override int item1
{
get
{
throw new NotSupportedException();
}
set
{
throw new NotSupportedException();
}
}
}
First of all this is not good idea if you using some methods, that operates base class.
You can try to use obsolete argument to make users twice think to use this property.
[System.Obsolete("Do not use this property",true)]
public override YourType YourProperty { get; set; }
What you are describing is something akin to 'private inheritance' from C++, and is not available in C#.
You cant do it directly, but you could override the properties in the child class and make them readonly e.g.
class Program
{
static void Main(string[] args)
{
b obj = new b();
obj.item1 = 4;// should show an error but it doent ???
}
}
class a
{
public virtual int item1 {get; set;}
public virtual int item2 { get; set; }
}
class b : a
{
public override int item1
{
get { return base.item1; }
set { }
}
}
class c : a
{
}
You could use interfaces to hide the property. The child class would implemented an interface that didn't have the property then it wouldn't appear.
You would need two interfaces for when you want the property and when you don't, thus making it a horrible hack.
You can override it and then Add a [Browsable(false)] tag to prevent showing it in designer.
Simple:
public class a:TextBox
{
[Browsable(false)]
public override string Text
{
get { return ""; }
set { }
}
}
Changing the accessibility of a virtual member is an inheriting class is specifically prohibited by the C# language spec:
The override declaration and the overridden base method have the same
declared accessibility. In other words, an override declaration cannot
change the accessibility of the virtual method. However, if the
overridden base method is protected internal and it is declared in a
different assembly than the assembly containing the override method
then the override method’s declared accessibility must be protected.
From section 10.6.4 Override methods
The same rules which apply to overriding method also apply to properties, so going from public to private by inheriting from the base class can't be done in C#.
What you actually need are interfaces:
public interface ProvidesItem1
{
int item1 { get; set; }
}
public interface ProvidesItem2
{
int item2 { get; set; }
}
class a : ProvidesItem1, ProvidesItem2
{
public int item1 { get; set; }
public int item2 { get; set; }
}
class b : ProvidesItem1
{
public int item1 { get; set; }
}
Then just pass the interfaces around. If the classes should use a common implementation, put that in a third class and let them derive from that class aswell as implement their respective interface.
Yes, it is possible. What say you on the delegation. I will try to give an idea of what is called "delegation" in OOP with a piece of code:
public class ClassA
{
// public
public virtual int MyProperty { get; set; }
// protected
protected virtual int MyProperty2 { get; set; }
}
public class ClassB
{
protected ClassC MyClassC;
public ClassB()
{
MyClassC = new ClassC();
}
protected int MyProperty2
{
get { return MyClassC.MyProperty2; }
set { MyClassC.MyProperty2 = value; }
}
protected int MyProperty
{
get { return MyClassC.MyProperty; }
set { MyClassC.MyProperty = value; }
}
protected class ClassC : ClassA
{
public new int MyProperty2
{
get { return base.MyProperty2; }
set { base.MyProperty2 = value; }
}
public override int MyProperty
{
get { return base.MyProperty; }
set { base.MyProperty = value; }
}
}
}
namespace PropertyTest
{
class a
{
int nVal;
public virtual int PropVal
{
get
{
return nVal;
}
set
{
nVal = value;
}
}
}
class b : a
{
public new int PropVal
{
get
{
return base.PropVal;
}
}
}
class Program
{
static void Main(string[] args)
{
a objA = new a();
objA.PropVal = 1;
Console.WriteLine(objA.PropVal);
b objB = new b();
objB.PropVal = 10; // ERROR! Can't set PropVal using B class obj.
Console.Read();
}
}
}
You can user new modifer.
Sample;
public class Duck
{
public string Color{get; set;}
public void Swim() { }
}
public class DonaldDuck : Duck
{
new public void Swim()
{
/*you could call in DonaldDuck.Swim only here but not public for DonaldDuck client.*/
}
}
If you wanna hide a member from base class then you will need to add a new base class let's call it baseA and your code should be as follows:
class Program
{
static void Main(string[] args)
{
b obj = new b();
obj.item1 = 4;// should show an error but it doent ???
}
}
class baseA
{
public int item2 { get; set; }
}
class a:baseA
{
public int item1 { get; set; }
}
class b : baseA { }
class c : a { }
See my comments in the code please, how can I get the concrete actiontype and why does the direct cast to a MyDto not work?
public class Gen1Layer<TData, TAction> : GenBaseLayer<TData, TAction>
{
public Gen1Layer(IGenBaseLayer<TData, TAction> layer) : base(layer) { }
public override Document<TData, TAction> ProcessDocument(Document<TData, TAction> document)
{
// Does not work!
// MyDto dto = (MyDto) document.Data;
// Does cast!
MyDto dto1 = document.Data as MyDto;
// Does not work!
MyConsts.ActionType bla = document.ActionType as MyConsts.ActionType;
// Does not work!
MyConsts.ActionType bla = (MyConsts.ActionType)document.ActionType;
}
}
The Gen1Layer is called this way:
IGenBaseLayer<MyDto,MyConsts.ActionType> layer = new Gen1Layer<MyDto,MyConsts.ActionType>(null);
Document<MyDto,MyConsts.ActionType> doc = new Document<MyDto,MyConsts.ActionType>(new MyDto(),MyConsts.ActionType.Add,new Session());
doc = layer.ProcessDocument(doc);
public class Document<TData,TAction>
{
public Document(TData data, TAction actionType,Session session)
{
Data = data;
ActionType = actionType;
Session = session;
}
public TData Data { get; set; }
public TAction ActionType { get; set; }
public Session Session { get; set; }
}
public class MyConsts
{
public enum ActionType
{
Get,
Add,
}
}
public interface IGenBaseLayer<TData, TAction>
{
Document<TData,TAction> ProcessDocument(Document<TData,TAction> document);
}
public class GenBaseLayer<TData,TAction> : IGenBaseLayer<TData,TAction>
{
public GenBaseLayer(IGenBaseLayer<TData,TAction> layer)
{
NextLayer = layer;
}
public IGenBaseLayer<TData,TAction> NextLayer { get; set; }
public virtual Document<TData,TAction> ProcessDocument(Document<TData, TAction> document)
{
Console.Write("Gen’s");
return document;
}
}
What I am trying to achieve is to have a generic baselayer and the derived layer(s) are of the concrete type in the overriden ProcessDocument method. I know this will break polymorphism that the IGenBaseLayer will never call the ProcessDocument method of the derived layer instance. But this is what I need. Every layer can have Document with different closed generic types like CustomerDto or SupplierDto and the related CustomerActionType or SupplierActionType.
The ActionType property of MyConsts is an enumeration type, whereas ActionType property of Document is of type TAction. TAction looks like a reference type and an enumeration is more like a value type. You can only cast reference types to another type if they inherit from that type. You cannot cast value types to a reference type. Your best bet is to add a getActionType() method on the Document class, process whatever TAction is, and return the corresponding enumeration. Before doing that, you should make the enumeration available to the Document class (perhaps define it outside of the MyConsts class?).
While what you are doing seems a bit sketchy
MyConsts.ActionType bla = (MyConsts.ActionType)Enum.
ToObject(typeof(MyConsts.ActionType), System.Convert.ToInt32(document.ActionType));
will accomplish what you are after at the expense of type safety.
I have a need to create a couple of classes that will serve as base classes for some data functionality I want to implement.
The first, we'll call SessionObjectDataItem looks like this ...
public class ObjectSessionDataItem
{
public int ID { get; set; }
public bool IsDirty { get; set; }
public bool IsNew { get; set; }
public bool IsRemoved { get; set; }
}
And next I want a List called ObjectSessionDataList and this is where I get stuck.
I can create the class OK ...
public class SessionObjectDataList<SessionObjectDataItem> : List<SessionObjectDataItem>
{
}
where I fall down is trying to define properties on the list that access items in it. For example, I want to write...
public List<SessionObjectDataItem> DirtyItems
{
get
{
return this.Where(d => d.IsDirty).ToList();
}
}
but VS refuses to recognise the SessionObjectDataItem property IsDirty inside the List object definition.
What I'm trying to end up with is a case where I might define
public class AssociatedDocument : SessionObjectDataItem
{
...
}
public class DocumentList : SessionObjectDataList
{
}
And then be able to say...
DocumentList list = new DocumentList();
...
foreach(AssociatedDocument doc in list.DirtyItems)
{
...
}
Can I actually do what it is that I'm attempting? Am I just doing it wrong?
Generic constraints will help here; you can write a container-class for which the generic type-parameter is constrained to be SessionObjectDataItem or one of its subtypes. This will allow you to construct a generic class that can hold instances of a specific sub-type of SessionObjectDataItem.
public class SessionObjectDataList<T> : List<T> where T : SessionObjectDataItem
{
public SessionObjectDataList<T> DirtyItems
{
get
{
return this.Where(d => d.IsDirty).ToList();
}
}
}
Usage:
var list = new SessionObjectDataList<AssociatedDocument>();
...
foreach(AssociatedDocument doc in list.DirtyItems)
{
...
}
Try to use the generic version Where<T> of the queryable interface:
public List<SessionObjectDataItem> DirtyItems
{
get
{
return this.AsQueryAble().Where<SessionObjectDataItem>(d => d.IsDirty).ToList();
}
}
Else Where simply assumes d as type Object.