如何将一个Dictionary变量用于两种不同类型?

时间:2019-09-25 16:35:03

标签: c# dictionary

我是C#的新手,想使用Dictionary <>

我的代码是这样的:

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;
}

在这种情况下,出现错误是因为我没有在其他情况下定义变量。

我试图这样做:

   Object progresses = null;
   if(obj1)
   {
      progresses = new Dictionary<string, object1>();
   }
   else if(obj2)
   {
      progresses = new Dictionary<string, object2>();
   }
   return progresses;

但是,它没有用。我遇到了“ progresses.ContainsKey()”和“ progresses.Add()”错误。

如何解决此问题? 我先谢谢了。

5 个答案:

答案 0 :(得分:0)

C#中没有像Java这样的菱形运算符可以访问封闭类型基础的开放泛型类型,从而防止了泛型多态性。

您只能使用由Dictionary类实现的非通用接口。

答案 1 :(得分:0)

如果要使用可以采用两种不同类型的通用字典,则它们必须基于相同的基类;否则,您必须使用非通用的。

除此之外,示例中的代码没有多大意义。首先,由于要返回IHttpActionResult的Task,因此无法在此处返回字典。您要么必须返回一个新的Task(例如,通过Task.Factory.StartNew()),要么等待返回IHttpActionResult并使用async / await语法的东西。

答案 2 :(得分:0)

突然冒出来的是您正在尝试将字典作为任务返回。那是您可能遇到的主要错误,以及为什么不能使用ContainsKey()或Add()的原因,因为这些不是Task对象的属性。我们也不知道object1 / obj1和object2 / obj2是什么。我同意其他人的看法,您应该明确说明您的目标是什么。

但是,由于不知道此方法是什么,它的用途是什么,并且不知道ASSUMING(总是一个糟糕的主意),obj1和obj2实际上是存在于全局范围内的东西,我会这样修改它:

    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;
    }

尽管这可能会失败,而且您无法将String,Dictionary的对象隐式转换为String,“ Object1”的字典,无论是什么...

答案 3 :(得分:0)

此代码存在许多问题。让我们逐一介绍一下。

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;
}

方法的返回类型为Task<IHttpActionResult>,但您尝试返回的是Dictionary,这是类型不匹配,并且出于显而易见的原因,编译器不喜欢它。因此,要解决的第一件事是将两者匹配,并且假设我们将返回类型更改为Dictionary。但是,现在您面临的问题是,您基于if试图返回两种不同类型的词典中的一种,这将不起作用。因此,现在让我们假设您总是返回一个Dictionary<string, Object1>,以便使编译器满意。现在您还可以注意到,我们已经在两个if语句之外声明了返回对象,因此也消除了该错误。我不确定您的obj1obj2是什么,所以我在使用一些随机条件。

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;
}

现在,编译器很高兴,但是在两种情况下您都返回相同类型的字典。我们该如何解决?如果您简化情况,则根据您的条件,您想返回一个string以及一个Object1Object2的实例。处理此问题的一种方法是为Object1Object2声明一个父类并创建该父类的字典。

public class ParentObject
{
}

public class Object1 : ParentObject
{
}

public class Object2 : ParentObject
{
}

然后,像这样创建字典:

Dictionary<string, ParentObject> progresses = new Dictionary<string, ParentObject>();

现在,根据条件,您可以将Object1Object2的实例添加到字典中。

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;
}

当您调用该方法并想知道接收到的对象的类型时,可以像这样获得其Type

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();

答案 4 :(得分:0)

要扩展先前的好答案,可以使用

缩短对象创建
    (ParentObject)Activator.CreateInstance(Type.GetType($"Object{id}"))

,您还可以将Object1和Object2基于接口,以使它们实现相同的方法,例如:

    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;
            }
    }

所以,以后在需要时使用它们:

    ((ParentObject)progresses[objectKey]).ObjectAction(value);