【问题标题】:C# check object type against multiple typesC# 针对多种类型检查对象类型
【发布时间】:2016-04-13 16:19:02
【问题描述】:

有没有办法将类型数组传递给“is”运算符?

我正在尝试简化针对多种类型检查对象的语法。

类似:

public static function bool IsOfType(object Obj,params Type[] Types)

然而,这需要以下用法:

if(X.IsOfType(typeof(int),typeof(float))
{...}

我想做这样的事情:

if(X is {int,float})

if(X.IsOfType(int,float))

甚至

public static bool ISOfType<T[]>(this object Obj){...}
if(X.ISOfType<int,float>())

我认为它们都是不可能的。

【问题讨论】:

  • 如果您编写的代码必须针对 basic 类型进行大量类型检查,CLR 本身使用的常用方法是 switchType.GetTypeCode。如果您发现自己经常针对非基本类型执行此操作,那么您的代码可能有问题,首先需要对此进行速记。
  • 要进一步@JeroenMostert 评论,这是check if the type is numeric 的方法。
  • 只需创建 IsNumeric 扩展函数。您不太可能真的需要针对多种任意类型检查对象。

标签: c# arrays generics


【解决方案1】:

如果您可以将类型作为泛型参数传递,那么有一个解决方案。不幸的是,C# 不支持可变参数泛型。您必须为每个通用参数定义函数。

public static bool IsOfType<T>(this object obj) => obj is T;
public static bool IsOfType<T1, T2>(this object obj) => obj is T1 || obj is T2;
public static bool IsOfType<T1, T2, T3>(this object obj) => obj is T1 || obj is T2 || obj is T3;
public static bool IsOfType<T1, T2, T3, T4>(this object obj) => obj is T1 || obj is T2 || obj is T3 || obj is T4;
public static bool IsOfType<T1, T2, T3, T4, T5>(this object obj) => obj is T1 || obj is T2 || obj is T3 || obj is T4 || obj is T5;
public static bool IsOfType<T1, T2, T3, T4, T5, T6>(this object obj) => obj is T1 || obj is T2 || obj is T3 || obj is T4 || obj is T5 || obj is T6;
public static bool IsOfType<T1, T2, T3, T4, T5, T6, T7>(this object obj) => obj is T1 || obj is T2 || obj is T3 || obj is T4 || obj is T5 || obj is T6 || obj is T7;
public static bool IsOfType<T1, T2, T3, T4, T5, T6, T7, T8>(this object obj) => obj is T1 || obj is T2 || obj is T3 || obj is T4 || obj is T5 || obj is T6 || obj is T7 || obj is T8;

我怀疑您是否需要超过 8 种类型,但如果需要,只需定义更多重载即可。

【讨论】:

  • 不是我想要的,但绝对是解决问题的有限方法。
  • 我的初始解决方案如下,但由于重用了 typeof(),在使用时仍然会产生冗长的结果: public static bool IsAnyOf(this object Obj,params Type[] Types) { foreach (Type Type in Types) if (Obj is Type) return true;返回假; }
  • 用法:ctxScript.Visible = !nSelected.IsAnyOf(typeof(TablesNode) ,typeof(ViewsNode) ,typeof(ProcedureNode) ,typeof(UserTableTypesNode) ,typeof(FunctionsNode) ,typeof(ServerNode) ,typeof (数据库节点));
  • @JeffHolodnak:您正在做的经典解决方案是访问者,为类提供具有虚拟ScriptOptionVisible 属性的公共基础。这使您可以添加新的节点类型,而无需在代码中必须添加新节点知识的所有位置。
【解决方案2】:

它看起来很疯狂,但您可以使用以下 Fluent 语法:

object someInstance = 5.0;
if(someInstance
    .Is<int>()
    .Or<double>()) {
    // ...
}

这里的fluent-syntax实现如下:

static class FluentIs {
    public static IsResult Is<T>(this object target) {
        return new IsResult(target, () => target is T);
    }
    public static IsResult Or<T>(this IsResult prev) {
        return new IsResult(prev, (v, x) => v || (x is T));
    }
    public class IsResult {
        Func<bool> value;
        object target;
        internal IsResult(IsResult r, Func<bool, object, bool> getValue) :
            this(r.target, () => getValue(r.value(), r.target)) {
        }
        internal IsResult(object target, Func<bool> value) {
            this.target = target;
            this.value = value;
        }
        // bool Operators
        public static bool operator true(IsResult r) { return r.value(); }
        public static bool operator false(IsResult r) { return !r.value(); }
    }
}

【讨论】:

    【解决方案3】:

    我的“选择”解决方案是使用我方便的“In”扩展函数根据对象类型名称进行验证。

        public static bool IsAnyOf(this object Obj,params string[] TypeNames)
        {
            return Obj.GetType().Name.In(TypeNames);
        }
        public static bool In(this string Needle,params string [] Haystack)
        {
            foreach (string straw in Haystack)
                if (straw == Needle)
                    return true;
            return false;
        }
    

    用法:

        public static void CheckAll(this TreeNode Node)
        {
            foreach(TreeNode Child in Node.Nodes)
            {
                if(Child.GetType().Name.In("ChildTablesNode","ChildTableNode"))
                {
                    Child.Checked = Node.Checked;
                    Child.CheckAll();
                }
            }
        }
    
        private void ctxTree_Opening(object sender, CancelEventArgs e)
        {
            TreeNode nSelected = Tree.SelectedNode;
    
            ctxScript.Visible = !nSelected.IsAnyOf("TablesNode"
                , "ViewsNode"
                , "ProceduresNode"
                , "UserTableTypesNode"
                , "FunctionsNode"
                , "ServerNode"
                , "DatabaseNode"
                , "ColumnsNode"
                , "ColumnNode"
                , "TriggersNode");
    
            Type[] x = { typeof(int) };
    
        }
    

    【讨论】:

      猜你喜欢
      • 2011-05-04
      • 1970-01-01
      • 2014-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-16
      相关资源
      最近更新 更多