1

我的情况是这样的。我需要在多种不同类型的对象上运行一些验证和按摩类型的代码,但为了清洁(和代码重用),我希望所有对这个验证外观的调用基本相同,而不管对象如何。我正试图通过重载来解决这个问题,直到我找到Generic Collection对象时,它才能正常工作。寻找在C中处理泛型集合的非特定类型的方法#

下面的例子应该澄清一下,我这里所说的:

 
    private string DoStuff(string tmp) { ... } 

    private ObjectA DoStuff(ObjectA tmp) { ... } 

    private ObjectB DoStuff(ObjectB tmp) { ... } 

    ... 

    private Collection<ObjectA> DoStuff(Collection<ObjectA> tmp) { 
     foreach (ObjectA obj in tmp) if (DoStuff(obj) == null) tmp.Remove(obj); 
     if (tmp.Count == 0) return null; 
     return tmp; 
    } 

    private Collection<ObjectB> DoStuff(Collection<ObjectB> tmp) { 
     foreach (ObjectB obj in tmp) if (DoStuff(obj) == null) tmp.Remove(obj); 
     if (tmp.Count == 0) return null; 
     return tmp; 
    } 

    ... 

这似乎是一个名副其实的垃圾,我不得不重复完全相同的代码为每一个不同的集合<牛逼>类型。我想做一个DoStuff的单个实例来处理任何Collection <T>,而不是为每个实例分别创建一个实例。

我尝试过使用ICollection,但是这有两个问题:第一,ICollection不公开.Remove方法,我不能编写foreach循环,因为我不知道列表中对象的类型。使用更通用的东西,比如Object,不起作用,因为我没有一个方法接受一个Object的DoStuff - 我需要它为实际的对象调用适当的方法。编写一个DoStuff方法,它接受一个对象,并执行一些if语句的大量列表来选择正确的方法并进行适当的转换,这种方法会破坏摆脱冗余代码的整个想法 - 我不妨复制并粘贴所有这些Collection <T>方法。

我一直在使用一个通用的DoStuff <牛逼>方法试过了,但是这有两个缺点 - 第一,它使每个调用必须声明,他们正在调用哪一个通用的方法(它们不再调用DoStuff(等等),他们有打电话给DoStuff <字符串>(等等))。其次,我在foreach循环中遇到同样的问题。因为我不知道设计时的对象类型,所以编译器不会让我调用DoStuff(obj)。

从技术上讲,编译器应该能够知道哪些调用需要在编译时进行,因为这些都是私有方法,并且调用中传递的对象的具体类型都是已知的方法被称为。这些知识似乎并没有引起这种方法调用的后续方法。

我真的不想在这里使用反射,因为这会使代码更复杂,而不仅仅是复制和粘贴所有的方法,并且会导致性能下降。有任何想法吗?

---编辑1 --- 我意识到我的泛型方法引用显示不正确,因为我没有使用尖括号的html代码。这应该现在修复。

--- EDIT 2 --- 根据下反应,我已经改变了我的收藏<牛逼>方法是这样的:

 
    private Collection DoStuff(Collection tmp) { 
     for (int i = tmp.Count - 1; i >= 0; i--) if (DoStuff(tmp[i]) == null) tmp.RemoveAt(i); 
     if (tmp.Count == 0) return null; 
     return tmp; 
    } 

这仍然不能正常工作,但是,由于当我调用DoStuff(tmp [i])时,编译器无法确定要调用哪个重载方法。

回答

1

像这样的事情?:

private Collection DoStuff<T>(Collection tmp) 
{ 
    // This will probably assert as you are modifying a collection while looping in it. 
    foreach (T obj in tmp) if (DoStuff(obj) == null) tmp.Remove(obj); 
    if (tmp.Count == 0) return null; 
    return tmp; 
} 

其中T是集合中的对象的类型。

请注意,你有一条很可能会断言的线。 SO:

private Collection DoStuff<T>(Collection tmp) 
{ 
    // foreach doesn't work if you are modifying the collection. 
    // Looping backward with an index, so we never encounter an invalid index. 
    for (int i = tmp.Count - 1; i >= 0; i--) if (DoStuff(tmp[i]) == null) tmp.Remove(tmp[i]); 
    if (tmp.Count == 0) return null; 
    return tmp; 
} 

但在这一点......为什么使它通用,因为你没有使用T-了吗?

private Collection DoStuff(Collection tmp) 
{ 
    // DoStuff can be generic, but you shouldn't need to explicitly pass it a type... 
    for (int i = tmp.Count - 1; i >= 0; i--) if (DoStuff(tmp[i]) == null) tmp.Remove(tmp[i]); 
    if (tmp.Count == 0) return null; 
    return tmp; 
} 
+1

制作''Collection'收集'我想你会找到答案:) –

+0

@MikeMcCaughan是集通用或没有?但即使是这样,我也看不出有什么理由知道它的类型,就像你在我最后一个例子中看到的那样。 DoStuff很可能是一个通用的。 – LightStriker

+0

嗯......好点。编译器必须知道'tmp [i]'是什么类型,并且可以转发到正确的过载。 –