Answer the question
In order to leave comments, you need to log in
C#. Is it possible to create a list of objects of a previously unknown type?
For example, there is such a class:
public class Value<T>
{
public Value()
{
}
public Value(T value)
{
this.value = value;
}
private T value;
}
public class Values: List<Value<T>>
Values v=new Values();
v.Add(new Value<int>());
v.Add(new Value<string>());
v.Add(new Value<MyType>());
Answer the question
In order to leave comments, you need to log in
It's hard to answer the question without an example of further use of the list.
1. Can do just create
List<object>and shove whatever you want in there.
List<BaseValue>.
Keeping objects of different types in the same list only makes sense if they inherit at least one common interface.
Suppose we decide to store all the forms of our application in the list - all forms have a common parent class, so we probably know the common methods. In this case, with objects of such a list, it will be reduced to this form:
Copy Source | Copy HTML
-
- using System.Reflection;
-
- // создаем наши формы
- List<object> objects = new List<object>();
- objects.Add( new Form1() );
- objects.Add( new Form1() );
- objects.Add( new Form2() );
- objects.Add( new Form3() );
-
- //отображаем их
- foreach( object obj in objects )
- {
- Type t= obj .GetType();
- Type[] tIncomingParams = {};
-
- MethodInfo methodInfo = type.GetMethod( "Show", tIncomingParams );
- methodInfo.Invoke( obj, null );
- }
-
This is possible by using covariance .
But with limitations:
Firstly, this is only possible in VS2010, the 2008 compiler does not support this. Specify the requirements for the framework on msdn, as far as I remember 3.5 sp1 is supported, although I may be wrong, and .net 4 is required for covariance.
Secondly, it will not be possible to parameterize the class with value types (for example, int).
Plus covariance imposes some other restrictions, which you can read about in the msdn link above.
Code example:
Copy Source | Copy HTML
- public interface IValue<out T>
- {
- T Get();
- }
-
- public class Value<T>:IValue<T>
- {
- public T Get()
- {
- return default(T);
- }
- }
-
- public class Values: List<IValue<object>>
- {
-
- }
Copy Source | Copy HTML
- var v = new Values();
- v.Add(new Value<string>());
- v.Add(new Value<object>());
-
- //а вот так нельзя: v.Add(new Value<int>());
-
Alternatively, use a list of type dynamic:
List x = new List();
Но по сути это то же, что и список Object'ов, только ещё медленнее работающий, но не требующий явного приведения типов в коде. Учтите, что использование dynamic может нанести ущерб производительности, т.к. за ним стоит рефлекшн. Пример:
Copy Source | Copy HTML
You are smart about something. What is wrong with a regular untyped list in this case?
List v = new List();
v.Add(new Value());
v.Add(new Value());
v.Add(new Value());
If it is not known in advance what types the elements will be, and at the same time they will need to be exported to some format, then converters are written for all standard types, and for the rest it is assumed that they must implement some kind of interface.
For example, like this:
protected Dictionary<Type, IExporter> Exporters { get; set; }
public void Export(object value, StreamWriter writer)
{
IExporter exporter = FindExporter(value.GetType());
if (exporter != null)
{
exporter.Export(value, writer);
}
else
{
writer.WriteString(value.ToString());
}
}
private IExporter FindExporter(Type type)
{
IExporter exporter = null;
if(Exporters.ContainsKey(type))
{
exporter = Exporters[type];
}
else
{
if(typeof(IMyFormatExportable).IsAssignableFrom(type))
{
exporter = new ExportAwareExporter(type);
}
}
return exporter;
}
public interface IMyFormatExportable
{
void Export(StreamWriter writer);
}
public MyClass : IMyFormatExportable
{
// ...
void Export(StreamWriter writer)
{
// writer.Write...(...);
}
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question