Reputation: 59
I am very new in C# and want to use Dictionary<>
My code is like this:
public Task<IHttpActionResult> GetProgress(int id)
{
if(obj1)
{
Dictionary<string, object1> progresses = new Dictionary<string, object1>
();
}
else if(obj2)
{
Dictionary<string, object2> progresses = new Dictionary<string, object2>
();
}
return progresses;
}
In this case, I got error because I did'n define the variable before if else.
I have tried to do like this:
Object progresses = null;
if(obj1)
{
progresses = new Dictionary<string, object1>();
}
else if(obj2)
{
progresses = new Dictionary<string, object2>();
}
return progresses;
However, it didn't work. I got error for "progresses.ContainsKey()" and "progresses.Add()".
How can I solve this problem? I appreciate in advance.
Upvotes: 0
Views: 474
Reputation: 528
To expand on previous great answer, you can shorten object createion using
(ParentObject)Activator.CreateInstance(Type.GetType($"Object{id}"))
and you can also base your Object1 and Object2 on an interface, to have them implement same methods, for example:
public interface ParentObject
{
int Id { get; set; }
void ObjectAction(int value);
}
public class Object1 : ParentObject
{
public int Id { get; set; }
public void ObjectAction(int value)
{
Console.WriteLine("I'm object #1 with value" + value);
}
}
public class Object2 : ParentObject
{
public int Id { get; set; }
public void ObjectAction(int value)
{
Console.WriteLine("I'm different object #2 with value" + value);
}
}
public class UsingDifferentObjects
{
public Dictionary<string, ParentObject> GetProgress(int id)
{
Dictionary<string, ParentObject> progresses = new Dictionary<string,ParentObject>();
var objtoAdd = (ParentObject)Activator.CreateInstance(Type.GetType($"Object{id}"));
objtoAdd.Id = id;
progresses.Add(id.ToString(), objtoAdd);
return progresses;
}
}
so, later when you need use them:
((ParentObject)progresses[objectKey]).ObjectAction(value);
Upvotes: 0
Reputation: 10393
This code has a multitude of problems. Let's go through each of them.
public Task<IHttpActionResult> GetProgress(int id)
{
if(obj1)
{
Dictionary<string, object1> progresses = new Dictionary<string, object1>
();
}
else if(obj2)
{
Dictionary<string, object2> progresses = new Dictionary<string, object2>
();
}
return progresses;
}
The return type of your method is Task<IHttpActionResult>
but you're trying to return a Dictionary
, which is a type mismatch and the compiler won't like it for obvious reasons. So the first thing to fix is to match the two, and let's say we change the return type to a Dictionary
. Now, however, you face the problem of based on your if
you're trying to return one of two different types of dictionaries, and that won't work. So for now let's assume you always return a Dictionary<string, Object1>
just so we can make the compiler happy. Now you can also notice that we've declared the return object outside the two if
statements so you get rid of that error as well. I'm not sure what your obj1
and obj2
are so I'm using some random condition in place.
public Dictionary<string, Object1> GetProgress(int id)
{
Dictionary<string, Object1> progresses = new Dictionary<string, Object1>();
if (id == 1)
{
progresses = new Dictionary<string, Object1>();
}
else if (id == 2)
{
progresses = new Dictionary<string, Object1>();
}
return progresses;
}
Now the compiler is happy, but you're returning a dictionary of the same type in both occasions. How can we fix it? If you boil the situation down, based on your condition you want to return a string
and an instance of either Object1
or Object2
. Well one way to handle this is to declare a parent class to Object1
and Object2
and create the dictionary of that parent class.
public class ParentObject
{
}
public class Object1 : ParentObject
{
}
public class Object2 : ParentObject
{
}
Then, create the dictionary like so:
Dictionary<string, ParentObject> progresses = new Dictionary<string, ParentObject>();
Now, based on condition you can either add an instance of Object1
or Object2
to the dictionary.
public Dictionary<string, ParentObject> GetProgress(int id)
{
Dictionary<string, ParentObject> progresses = new Dictionary<string, ParentObject>();
if (id == 1)
{
var o1 = new Object1();
progresses.Add(id.ToString(), o1);
}
else if (id == 2)
{
var o2 = new Object2();
progresses.Add(id.ToString(), o2);
}
return progresses;
}
When you're calling the method and wants to know which type of an object you received, you can get the Type
of it like so:
var result1 = GetProgress(1);
// Here, type = Object1
var typeOfObject1 = result1.First().Value.GetType();
var result2 = GetProgress(2);
// Here, type = Object2
var typeOfObject2 = result2.First().Value.GetType();
Upvotes: 1
Reputation: 594
The thing that pops out to me is that you are trying to return a Dictionary as a Task. That's the primary error you're probably coming across, and why you can't use ContainsKey() or Add(), because those aren't properties of a Task object. We also don't know what object1/obj1 and object2/obj2 are. I concur with the others, you should state what exactly your goal is.
However, not knowing what this method is, or what it's for, and ASSUMING (always a terrible idea), that obj1 and obj2 are things that do in fact exist on the global scope, I'd modify it like this:
public Dictionary<string, object> GetProgress(int id)
{
Dictionary<string, object> returnValue;
if(obj1)
{
Dictionary<string, object1> progresses = new Dictionary<string, object1>();
}
else if(obj2)
{
Dictionary<string, object2> progresses = new Dictionary<string, object2>();
}
return progresses;
}
Though that might fail as well as you can't implicitly convert a Dictionary of String, Object into a Dictionary of String, "Object1", whatever that is...
Upvotes: 0
Reputation: 206
If you want to use a generic dictionary that can take two different types, they need to be based on the same base class; otherwise, you have to use a non-generic one.
Apart from that, the code in your example doesn't make much sense. First of all, since you are returning a Task of IHttpActionResult, you cannot return a dictionary here . You either have to return a new Task (via Task.Factory.StartNew()
, for example) or await something that returns an IHttpActionResult and use async/await syntax.
Upvotes: 0
Reputation:
There is no diamond operator in C# like in Java that allows to access the open generic type underlying to closed types, which prevents generic polymorphism.
You can only use non generic interfaces implemented by the Dictionary class.
Upvotes: 0