Reputation: 11
Is it possible to have generic types and non-generic types in one class??
I have a class in which I have to manage different types but I don't know exactly what I'm going to receive, I though about using generics but I have not found a way for doing this.
This is what I am trying to do
int commandCode;
<T> arg1;
<T> arg2;
<T> arg3;
I have to read 4 string lines out of a text file, and try to parse those lines into
(First trying to parse it to 1, if not possible to 2, if not possible to 3, if not possible to 4.)
And after knowing what type is each argument, define each variable with the its respective type
For instance with a text file with
I would have an object with
And that would happen for any combination possible for arg1 to arg3.
Upvotes: 1
Views: 88
Reputation: 45071
If you have variable types depending on the data you read (like in your case) it doesn't make much sense to use generics. Even if you take @Spontifixus approach you are not able to put all the created elements in one List<T>
, cause due to the different types used in each object you need for each combination your own List<T>
. Also if you later in code like to work with all the arguments, you need to query for each generic type to know how to read the desired value out of the current instance.
If you still think you need generic types (in this case) you can help yourself by using a generic class a creator method and a normal interface:
public interface ICommand
{
int CommandCode { get; set; }
object Argument1 { get; }
object Argument2 { get; }
object Argument3 { get; }
}
public static class Command
{
public static Command<T1, T2, T3> Create<T1, T2, T3>(int code, T1 arg1, T2 arg2, T3 arg3)
{
return new Command<T1, T2, T3>(code, arg1, arg2, arg3);
}
}
public class Command<T1, T2, T3> : ICommand
{
public Command(int code, T1 arg1, T2 arg2, T3 arg3)
{
CommandCode = code;
Argument1 = arg1;
Argument2 = arg2;
Argument3 = arg3;
}
public int CommandCode { get; set; }
public T1 Argument1 { get; set; }
public T2 Argument2 { get; set; }
public T3 Argument3 { get; set; }
object ICommand.Argument1
{
get { return Argument1; }
}
object ICommand.Argument2
{
get { return Argument2; }
}
object ICommand.Argument3
{
get { return Argument3; }
}
}
By using this approach you can create a instance through type inference by calling the creator method and put all of them in one list:
var commands = new List<ICommand>();
var myCommand = Command.Create(3, 4f, true, "hello world");
var commands.Add(myCommand);
Now you got your generic objects in one list, but how do you work with this list? At last you're going all the time using the ICommand
interface and stick to the object
, making the generics useless. But maybe you don't think so and this approach might help.
Upvotes: 0
Reputation: 21742
If I understnad you correctly you can only determine the actual type at runtime. In that csae generics won't help you much since any type argument needs to be resolved at compile time therefor you need to use reflection in some manner. Below is a factory that could be extended to support your needs. You might or might not need 16 different methods depending on how many subclasses you have in reality (you'd need one for each subclass with the below approach) you could also skip the Create method and select the appropriate class/constructor directly
public class Command {
public static Command Create(string[] textLines) {
var args = textLines.Select(l => parseLine(l));
var argTypes = args.Select(a => a.GetType().ToArray();
return (Command)typeof(Command).GetMethod("Create",argTypes).Invoke(null,args);
}
public static Command Create(int commandType,
bool IsSponk,
int count,
string description){
return new CommandType1(commandType,
IsSponk,
count,
description);
}
private class CommandType1 : Command {
public CommandType1(int commandType, bool IsSponk, int count, string description){
....
}
}
}
Upvotes: 1