簡體   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