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



我对C#很陌生,想使用字典<>

我的代码是这样的:

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;

但是,它没有奏效。我收到"进度"的错误。包含键(("和"进展。添加(("。

如何解决这个问题? 我提前表示赞赏。

这段代码有很多问题。让我们逐一介绍一下。

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

C# 中没有像 Java 那样允许访问封闭类型底层的开放泛型类型的菱形运算符,这可以防止泛型多态性。

只能使用由 Dictionary 类实现的非泛型接口。

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

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

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

但是,不知道这种方法是什么,或者它的用途是什么,并且假设(总是一个糟糕的想法(,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;
}

虽然这可能会失败,因为您无法隐式地将字符串字典、对象转换为字符串字典、"Object1",不管那是什么......

要扩展以前的精彩答案,您可以使用以下方法缩短对象创建时间

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

最新更新