簡體   English   中英

除了在C#接口中使用靜態方法之外,還有其他方法嗎?

[英]Anyone has an alternative to using static methods in a C# interface?

我想實現一個集合,該集合的項目需要進行空性測試。 如果是引用類型,則將測試是否為空。 對於值類型,必須執行空測試,並可能選擇一個表示空的特定值。

我的T的通用集合應該對值和引用類型值都可用(意味着Coll<MyCalss>Coll<int>都應該是可能的)。 但是我必須以不同的方式測試引用和值類型。

有一個實現IsEmpty()方法的接口將這種邏輯從我的泛型類型中排除是不是很好? 但是,當然,此IsEmpty()方法不能是成員函數:不能在空對象上調用它。

我發現的一種解決方法是將收集項目存儲為對象,而不是Ts,但這使我頭疼(圍繞拳擊和強類型輸入)。 在舊的C ++中,這沒問題:-)

下面的代碼演示了我想要實現的目標:

using System;
using System.Collections.Generic;

namespace StaticMethodInInterfaceDemo
{
  public interface IEmpty<T>
  {
    static T GetEmpty();  // or static T Empty;

    static bool IsEmpty(T ItemToTest);
  }


  public class Coll<T> where T : IEmpty<T>
  {
    protected T[] Items;

    protected int Count;


    public Coll(int Capacity)
    {
      this.Items = new T[Capacity];
      this.Count = 0;
    }

    public void Remove(T ItemToRemove)
    {
      int Index = Find(ItemToRemove);

      // Problem spot 1: This throws a compiler error: "Cannot convert null to type parameter 'T'
      // because it could be a non-nullable value type. Consider using 'default(T)' instead."
      this.Items[Index] = null;

      // To overcome, I'd like to write this:
      this.Items[Index] = T.Empty;  // or T.GetEmpty(), whatever.

      this.Count--;
    }


    public T[] ToArray()
    {
      T[] ret = new T[this.Count];

      int TargetIndex = 0;
      for(int Index = 0; Index < this.Items.GetLength(0); Index++)
      {
        T Item = this.Items[Index];

        // Problem spot 2: This test is not correct for value types.
        if (Item != null)
          ret[TargetIndex++] = Item;

        // I'd like to do this:
        if (!T.IsEmpty(Item))
          ret[TargetIndex++] = Item;
      }

      return ret;
    }

    protected int Find(T ItemToFind)
    {
      return 1;  // Not implemented in the sample.
    }
  }
}

您可以為接口創建一個名為IsEmpty的擴展方法 然后,您可以先測試此擴展方法中的'this'參數是否為null。

因此,您可以在對實現您的接口的類型的任何引用上調用IsEmpty方法,而不用考慮它是否可以為null。

您可以為此使用'default'關鍵字,如下所示:

this.Items[Index] = default(T);

沒有 “空” int 這樣的東西 ,因此除非您存儲已定義的位圖,否則支持int會很棘手-但是,如果僅使用int?的集合int? (即Nullable<int> )已為您完成 沒有額外的工作,也沒有拳擊:

List<int?> list1 = ...; // data
List<string> list2 = ...; // data

Console.WriteLine(list1[3]; == null); // actually maps to `item.HasValue`
Console.WriteLine(list2[3]; == null); // reference test

為了得到一個intint? , 任何:

int i = (int)value; // throws exception if empty
int i = i.Value; // throws exception if empty
int i = i.GetValueOrDefault(); // returns 0 if empty

當您不需要測試是否為空時,只需一個List<int> (否? )。 沒有多余的代碼。 沒有特殊的收藏班。 它適用於大多數情況。

不要在類中使用數組來表示集合,而應使用堆棧或列表。 那么您就沒有空索引,如果將它們刪除,它們根本就不存在。

只在構造函數中發送兩個函數怎么樣?

public Coll(Func<T> createEmpty, Func<T, bool> isEmpty)
{
    this.createEmpty = createEmpty;
    this.isEmpty = isEmpty;
}

然后,您可以稍后使用這些功能:

if (!isEmpty(item))

Items[index] = createEmpty();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM