Generic list of generic objects
Yes, generics is a good choice. The key to achieving type-safety (and being identify the type with the Type
property is to add an abstraction between the list and Field<T>
class.
Have Field<T>
implement the interface IField
. This interface doesn't need any members.
Then declare your list as being List<IField>
.
That way you constrain the list to only contain fields, but each field can be of a different type.
To then read the values later, just do
foreach(var field in list)
{
var type = field.Type;
....
}
A generic list of generics
This is situation where it may benefit you to have an abstract base class (or interface) containing the non-generic bits:
public abstract class Field
{
public string Name { get; set; }
public string Description { get; set; }
}
public class Field<T> : Field
{
public T Value { get; set; }
/*
...
*/
}
Then you can have a List<Field>
. That expresses all the information you actually know about the list. You don't know the types of the fields' values, as they can vary from one field to another.
How to return Generic List with Generic Class Object in c#?
You can't use generic type with the List without specifying type parameter explicitly. Alternatively, you can create a base class or interface that would be a parameter for the List.
I mean:
public static List<ITable> GetTables()
{
var tbls = new List<ITable>();
tbls.Add(new Table<Table1> { Name = "Table1"});
tbls.Add(new Table<Table2> { Name = "Table2"});
tbls.Add(new Table<Table3> { Name = "Table3"});
return tbls;
}
public class Table<T> : ITable
{
public T TableInstance { get; set; }
public Type TableType => typeof(T);
public string Name { get; set; }
}
public interface ITable
{
Type TableType { get; }
public string Name { get; set; }
}
Adding generic object to generic list in C#
I don't think you can do this in C#... you would have to add the type parameter to the class:
class C<T> {
void Method(SomeClass<T> obj) {
list.Add(obj);
}
List<SomeClass<T>> list = new List<SomeClass<T>>();
}
The other option would be to use an interface:
class C {
void Method<T>(T obj)
where T : ISomeClass {
list.Add(obj);
}
List<ISomeClass> list = new List<ISomeClass>();
}
Generic list of generics with same base class
Change
var carArea = new Area<Car> { Vehicles = new List<Car>() };
var bikeArea = new Area<Bike> { Vehicles = new List<Bike>() };
To
var carArea = new Area<Vehicle> { Vehicles = new List<Car>() };
var bikeArea = new Area<Vehicle> { Vehicles = new List<Bike>() };
Now your carArea
and bikeArea
is a Area<Vehicle>
(which your garage expects) and each have its own related vehicles, which will work in your methods.
and to get the type of vehicle in the list:
if(area.GetType() == typeof(List<Car>))
{
}
How to make a List of Generic Objects?
Is there a way I can define a member with a type that mans "Children classes will contain a _valeur class variable, I don't know what type is that variable, children will define it".
Sure - use object
as the type:
protected object _valeur;
Think about it - if _valeur
can be of different types - how do you know what type you're dealing with at compile time? And so how do you use it?
Take List<T>
for example - suppose you want a List<List<?>>
, where the inner list can be of any type. Right now you can use List<object>
, you can even use List<IEnumerable<object>>
to guarantee that the inner lists are at least some form of IEnumerable<T>
. But let's suppose your syntax existed:
var funkyList = new List<List<?>>();
I can now add lists of any type:
funkyList.Add(new List<int>());
funkyList.Add(new List<Foo>());
funkyList.Add(new List<Bar>());
Now you extract one of the inner List
s:
List<?> l = funkyList[1];
But what is ?
? If you don't know what the type of the list is, how are you going to do anything useful with it? At best you'd have to use reflection (or dynamic
) to get the inner type anyways, which negates the power of generics.
List of generic objects compared to single generic object
First: Dont use raw types. What is a raw type and why shouldn't we use it?
A way to fix your code would be to introduce type paramters to the methods of the factory.
class Factory{
public static <T> GenericObject<T> getSingleInstance()
{
return new GenericObject<T>();
}
public static <T> List<GenericObject<T>> getListOfInstance()
{
List<GenericObject<T> genericObjectList=new ArrayList<>();
genericObjectList.add(new GenericObject<T>());
genericObjectList.add(new GenericObject<T>());
return genericObjectList;
}
}
Reading Generic Value from List of Generic Objects
You have syntax errors in the code like the lacking public scope of your enums and ConditionOperator.Equal
(not ConditionOperator.Equals
) but that asside here is the fix.
Conditions
should be of typeList<ConditionBase>
- Use
OfType
on the List to retrieve and cast the resulting type toCondition<string>
. I assume that this was your intention with your added checkc.GetType() == typeof(string)
string url = "";
List<ConditionBase> Conditions = new List<ConditionBase>();
Conditions.Add(new Condition<int>(Field.Field1, 1, ConditionOperator.Equal));
Conditions.Add(new Condition<string>(Field.Field2, "test", ConditionOperator.NotEqual));
foreach (var c in Conditions.OfType<Condition<string>>())
{
url += c.Field + " " + c.ConditionOperator + " '" + c.Value + "' and ";
}
If you want a generic property that you can access on all instances regardless of the generic type constraint then you would need to extend the base interface accordingly.
public interface ConditionBase
{
Field Field { get; set; }
ConditionOperator ConditionOperator { get; set; }
object FieldValue { get; }
}
public class Condition<T> : ConditionBase
{
/* I only included the added code in this type */
public object FieldValue
{
get { return (object) this.Value; }
}
}
string url = "";
List<ConditionBase> Conditions = new List<ConditionBase>();
Conditions.Add(new Condition<int>(Field.Field1, 1, ConditionOperator.Equal));
Conditions.Add(new Condition<string>(Field.Field2, "test", ConditionOperator.NotEqual));
foreach (var c in Conditions)
{
url += c.Field + " " + c.ConditionOperator + " '" + c.FieldValue + "' and ";
}
It seems you want to output your value to a string based on the changes in your question. Add a string formatter to your type.
/* I only included the added code in this type */
public class Condition<T> : ConditionBase
{
private Func<T, string> _formatValue;
public Condition(Field field, T value, ConditionOperator condition, Func<T, string> formatValue)
{
this._Field = field;
this._Value = value;
this._ConditionOperator = condition;
this._formatValue = formatValue;
}
public override string ToString()
{
return this._formatValue(this.Value);
}
}
string url = "";
List<ConditionBase> Conditions = new List<ConditionBase>();
Conditions.Add(new Condition<int>(Field.Field1, 1, ConditionOperator.Equal, (val)=> val.ToString()));
Conditions.Add(new Condition<string>(Field.Field2, "test", ConditionOperator.NotEqual, (val)=> val));
foreach (var c in Conditions)
{
url += c.Field + " " + c.ConditionOperator + " '" + c.ToString() + "' and ";
}
Adding Object to Generic List with two types
List<SubClaz>
is not a subtype of List<SuperClaz>
in Java. That's why the wildcards are used: List<SubClaz>
is a subtype of List<? extends SuperClaz>
.
Now for your A<B<?>> abcv=new A<B<String>>();
example:
By adding the wildcard, you're making B<String>
a subtype of B<?>
, but since these are also wrapped by another type A
, we're back to the first problem:A<B<String>>
is not a subtype of A<B<?>>
(Notice B<?>
is the SuperClaz
and B<String>
is the SubClaz
in this case).
You can fix this the same way; by adding another wildcard: A<B<String>>()
is a subtype of A<? extends B<?>>
.
Keep in mind that this doesn't allow you to read or manipulate the list as you want. Search for covariance and contravariance for more detail. Here is a good one: http://bayou.io/draft/Capturing_Wildcards.html
Related Topics
Equivalent of Tuple (.Net 4) for .Net Framework 3.5
How to Get Modified Date from File in C# on Windows Mobile
Excluding Some Properties During Serialization Without Changing the Original Class
How to Use C# 8 with Visual Studio 2017
How to Pass Objects into an Attribute Constructor
C#: Cast to Generic Interface with Base Type
Where Are Clr-Defined Methods Like [Delegate].Begininvoke Documented
Can't See Localhost from Uwp App
Thread with Multiple Parameters
Dynamically Cross-Join Multiple Different-Size Collections Together in Linq (C#)
How to Disable the Horizontal Scrollbar in a Panel
C# Open File, Path Starting with %Userprofile%