[英]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
為了得到一個int
從int?
, 任何:
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.