繁体   English   中英

我如何创建一个 object 作为稍后放置的数据(例如整数)的“合同”?

[英]How can I create an object which acts as a “contract” for data (e.g an integer) to be placed there later?

我正在用不同类型的项目填充对象 [] - 例如 [string, int, DateTime]。 某些值取决于仅在以后(实时)可用的数据。 我想在数组中为这个数据创建一个“合同”,然后当数据可用时,将“合同”object 换成实际数据。 因此,如果它是一个合同,那么我可以稍后将合同更改为一个字符串。 我在这里以一种独特的方式使用术语“合同”,不一定与您可能熟悉的该术语的任何其他用途相关。 如果它变得令人困惑,我愿意放弃这个术语,它只是帮助我概念化我的用例。

起初我尝试重载 int cast 运算符:

// Expected types: string, int, DateTime
object[] Item = new object[] { 
    "hello", new Contract<int>(), DateTime.Now()
}

public class Contract<T>
{
    public static implicit operator int(Contract<T> Contract)
    {
        // Here the data would be actually resolved
        return 0;
    }
}

但是,在使用object[] Item的客户端代码(在我无法控制的引用程序集中)中,出现以下错误: expected System.Int32 but found Namespace.Contract `1[System.Int32] 显然,如果我理解此错误消息(我可能不理解),客户端代码需要一个 Int32 值,但会收到一个装在合同内的 Int32。

我想尝试这样做的一种方法是:

// Expected types: string, int, DateTime
object[] Item = new object[] { 
    "hello", new Contract<int>(), DateTime.Now()
}

// Interface to allow creating a List of generics
public interface IContract {}

List<IContract> Contracts = new List<IContract>();

public class Contract<T> : IContract
{
    public Contract()
    {
        Contracts.Add(this);
    }    

    public static implicit operator int(Contract<T> Contract)
    {
        // Here the data would be actually resolved
        return 0;
    }
}

// And later on
foreach (var Contract in Contracts)
{
    Contract = (int)(Contract<int>)Contract;
}

但是由于明显的原因 foreach 迭代变量是不可变的。

困难在于,当客户端代码来评估数组的内容时,它需要一个 integer 但找到一个装箱值。 如果它是动态的,它仍然会遇到 Contract object 而不是它期望的 int。 我重载了 int 类型转换操作符,希望它能转换成它期望的类型,但事实并非如此。 我真的需要某种方法,要么a)在客户端代码评估类型时自动取消装箱,要么b)自己事先手动取消装箱。

关于如何进行的任何想法? 我愿意完全改变为不同的模式。 首先在没有正确数据的情况下初始化 object[] 的想法似乎被误导了。 如果在数据可用时有更好的方法来解析数组数据,我很感兴趣。

稍微改变了方向,现在有了一个可行的解决方案。

// First, got rid of the complicated generic and interface
public class Contract
{
    // The target array to modify
    public object[] Target { get; set; }
    // Index to the item in the target array
    public int Index { get; set; }

    public void Resolve()
    {
        // Change the value stored in the target array from Contract to int
        Target[Index] = 0;
    }
}

List<Contract> Contracts = new List<Contract>();

// Expected types: string, int, DateTime
object[] Items = new object[] { 
    "hello", new Contract(), DateTime.Now()
}

// A preprocessing step for Items array
foreach (var Item in Items)
{
    if (Item is Contract)
    {
        var Contract = (Contract)Item;
        Contract.Index = Index;
        Contract.Target = Items;
        Contracts.Add(Contract);
    }
}

// Later
foreach(var Contract in Contracts)
{
    Contract.Resolve();
}

Items 的预处理步骤是更改导致的主要开销。 rest 被简化。 实际的实现比这里显示的要复杂一些,并且有更详细的要求。 这显示了达成解决方案的关键概念。 感谢评论者的帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM