c# - 检查变量是否是正确的类型及其 T if 指定的接口
问题描述
=== 已解决问题并将最佳解决方案添加到代码中 ===
你好我有以下问题。正如您在下面的代码中看到的,我有一个包含命令的命令堆栈。有不止一种类型的命令,每个命令类可以有不同的 T 参数,虽然这只能是继承 IModel 接口的类。
现在,当我想检查某种类型的命令当前是否在堆栈中时。我(直到我做错了)必须用模板指定整个类型,这非常不方便,因为它可能导致很长的 if-else 语句。
我想指定类类型,但我不关心它的模板类型。有没有办法做到这一点?
在您可以复制并运行的整个代码下方。它是完全可执行的,并且准确地显示了我想要实现的目标。
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
public interface IModel { }
class SomeDataModelA : IModel { }
class SomeDataModelB : IModel { }
// in reality there is more models and all of them implements IModel
public interface IUndoRedoCommand
{
void Undo();
void Redo();
}
class RemoveCommand<IModel> : IUndoRedoCommand
{
public void Undo() => throw new NotImplementedException();
public void Redo() => throw new NotImplementedException();
}
class AddCommand<IModel> : IUndoRedoCommand
{
public void Undo() => throw new NotImplementedException();
public void Redo() => throw new NotImplementedException();
}
public class UndoRedoList<T> : List<T>
where T : IModel
{
readonly CommandStack _commandStack;
public UndoRedoList(CommandStack commandStack)
: base()
{
_commandStack = commandStack;
}
public UndoRedoList(int capacity, CommandStack commandStack)
: base(capacity)
{
_commandStack = commandStack;
}
public UndoRedoList(IEnumerable<T> enumerable, CommandStack commandStack)
: base(enumerable)
{
_commandStack = commandStack;
}
public void AddWithUndoRedoTracking(T item)
{
Add(item);
_commandStack.Push(new AddCommand<T>());
}
public void RemoveWithUndoRedoTracking(T item)
{
Remove(item);
_commandStack.Push(new RemoveCommand<T>());
}
public void InsertWithUndoRedoTracking(int index, T item)
=> _commandStack.Push(new AddCommand<T>());
}
public class CommandStack
{
public int UndoCount => _pointer;
public int RedoCount => _undoRedoStack.Count - _pointer;
readonly IList<IUndoRedoCommand> _undoRedoStack = new List<IUndoRedoCommand>();
int _pointer; // points at first redo - so first undo will be _pointer - 1
public void Push(IUndoRedoCommand cmd) => _undoRedoStack.Insert(_pointer++, cmd);
public void Refresh()
{
for (int i = 0; i < _undoRedoStack.Count; i++)
{
IUndoRedoCommand cmd = _undoRedoStack[i];
if (cmd is AddCommand<IModel>)
Console.WriteLine("This doesn't work but it should.");
if(cmd is AddCommand<SomeDataModelA>
|| cmd is AddCommand<SomeDataModelB>
/* and so on for all models*/)
Console.WriteLine("This works but it is ugly.");
// perfect solution by Sweeper
if (cmd.GetType().GetGenericTypeDefinition() == typeof(AddCommand<>))
Console.WriteLine("This works too!! Thank you Sweeper.");
}
}
}
class Program
{
static void Main()
{
var stack = new CommandStack();
var list = new UndoRedoList<SomeDataModelA>(stack);
list.AddWithUndoRedoTracking(new SomeDataModelA());
list.AddWithUndoRedoTracking(new SomeDataModelA());
stack.Refresh();
}
}
}
解决方案
您可以使用GetType().GetGenericTypeDefinition()
,并将类型与 进行比较==
:
if(cmd.GetType().GetGenericTypeDefinition() == typeof(AddCommand<>)) {
}
请注意,如果您希望 的子类AddCommand
也输入if
.
推荐阅读
- ms-access - 访问:记录锁定 - 编辑的记录属性无法正常工作
- sql - 有条件地选择多行并将其插入 SQL Server 中的单行
- java - Google Play:在此服务器上找不到请求的 URL
- sql - AWK - 解析 SQL 输出
- arrays - 获取“第 11 行:[:9:预期一元运算符”
- java - 如何执行 MySQL sql '开始...结束;' 使用 JDBC
- php - PHP 函数可以期望一个类型吗?
- android - 在 Android NDK 中链接静态库
- javascript - 创建一个在打开它的按钮旁边打开的模式
- python - Tkinter - 在窗口中创建保存按钮?