任何人都可以在C#界面中使用静态方法吗?

时间:2009-11-28 11:40:33

标签: c# interface static methods

我想实现一个集合,其项目需要进行空虚测试。 在引用类型的情况下,将测试为null。对于值类型,必须实现空测试,并且可能选择表示空白的特定值。

我的T的通用集合应该可用于值和引用类型值(意味着Coll<MyCalss>Coll<int>都应该是可能的。但我必须以不同方式测试参考和值类型。

有一个实现IsEmpty()方法的接口,从我的泛型类型中排除这个逻辑,这不是很好吗?但是,当然,这个IsEmpty()方法不能是成员函数:它不能在空对象上调用。

我找到的一个解决方法是将收集项目存储为对象,而不是T-s,但它让我头疼(围绕拳击和强类型)。在旧的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.
    }
  }
}

5 个答案:

答案 0 :(得分:7)

您可以为名为IsEmpty的界面创建扩展方法。然后你可以先测试这个扩展方法中的'this'参数是否为空。

因此,你可以在对实现你的接口的类型的任何引用上调用IsEmpty方法,而不是关于它是否为null。

答案 1 :(得分:3)

您可以使用'default'关键字,如:

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

答案 2 :(得分:3)

没有这样的东西是一个“空”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>(无?)。没有额外的代码。没有特别的收藏类。它适用于大多数事情。

答案 3 :(得分:0)

不使用类中的数组来表示集合,而是使用堆栈或列表。那么你没有空索引,如果它们被删除,它们就不存在。

答案 4 :(得分:0)

如何在构造函数中发送两个函数?

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

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

if (!isEmpty(item))

Items[index] = createEmpty();