c# - 替代使用标记接口(interface)来测试派生泛型类?

标签 c# generics interface marker-interfaces

我有一个应用程序,它使用来自公共(public)基类的多种类型的派生类,并且有几个派生类使用泛型。应用程序经常需要遍历派生类的集合并识别特定的类类型以进行特殊处理。

问题是如何在不知道类型的情况下以简洁优雅的方式测试基类的特定泛型派生(因为它在项目中经常这样做)?

'is' 运算符不适用于此:

if (item is MyDerivedGenericClass<>)  // Won't compile

为了解决这个问题,我正在考虑使用空标记接口(interface)来识别集合中的特殊类。这似乎是最干净的解决方案。

一些注意事项:

  • 这是一个封闭的项目,不会成为商业分布式库。
  • 标记接口(interface)标记的类被标记为永久唯一类型,并且该类型的所有派生类都将正确继承标记。

下面的例子:

public interface MarkerA { }  // Empty Interface
public interface MarkerB { }  // Empty Interface
public interface MarkerC { }  // Empty Interface

public class BaseClass { }

public class DerivedClassA : BaseClass { }
public class DerivedClassB : BaseClass { }
public class DerivedClassC : BaseClass { }

public class DerivedSpecialClass : BaseClass { }

public class DerivedSpecialA : DerivedSpecialClass { }
public class DerivedSpecialB : DerivedSpecialClass { }
public class DerivedSpecialC : DerivedSpecialClass { }

public class DerivedSpecialGenericA<T> : DerivedSpecialClass, MarkerA { }
public class DerivedSpecialGenericB<T> : DerivedSpecialClass, MarkerB { }
public class DerivedSpecialGenericC<T> : DerivedSpecialClass, MarkerC { }


public void ProcessClasses(List<BaseClass> list)
    {
        // Iterate through a list of mixed classes that all derive from BaseClass
        foreach (BaseClass item in list)
        {

            // Ideal approach, but doesn't compile:

            // Try to isolate select class types to do something interesting with
            if ((item is DerivedSpecialA) || (item is DerivedSpecialB) || (item is DerivedSpecialGenericB<>))
            {
                var specialItem = item as DerivedSpecialClass;

                DoSomethingInteresting(specialItem);

                Console.WriteLine(specialItem.Title);
            }


            // Alternative workaround that tests for the Marker instead

            // Try to isolate select class types to do something interesting with
            if ((item is DerivedSpecialA) || (item is DerivedSpecialB ) || (item is MarkerB))
            {
                var specialItem = item as DerivedSpecialClass;

                DoSomethingInteresting(specialItem);

                Console.WriteLine(specialItem.Title);
            }
        }
    }

有没有人对如何解决这个问题有更好的想法?

谢谢。

最佳答案

当我需要根据对象类型编写不同的代码,并且该代码作为虚拟方法不实用时,我使用实现为返回不可变信息的虚拟属性的标识符。这更干净,并且不使用额外的实例存储,尽管通过类型参数初始化 MarkerType 会很好。

public class BaseClass 
{
    public abstract MarkerType { get; }  
}

public enum MarkerType { A, B, C }

关于c# - 替代使用标记接口(interface)来测试派生泛型类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18641070/

相关文章:

c# - .NET MAUI 将列表绑定(bind)到上下文 View

java - 使用菱形运算符创建通用数组

Java - 如何对通用 ArrayList 进行子类化,以便 MyArrayList<foo> 的实例成为 ArrayList<foo> 的子类?

ios - RxSwift - 绑定(bind)到 tableView 的可选问题

c# - C# 中的停靠面板套件不会触发 mousedown 事件

c# - 如何创建一个 web Api 具有 http post 功能,它可以从正文中获取任何动态 json 内容并能够将其解析为字符串

c# - LINQ 选择特定元素

syntax - 关键字 var 后的下划线和接口(interface)名称是什么意思?

java - 重写clone()方法时,为什么需要将其声明为public?

java - 接口(interface)类型转换困境