首页 文章

通用方法多(OR)类型约束

提问于
浏览
108

阅读this,我了解到有可能允许方法通过使其成为通用方法来接受多种类型的参数 . 在该示例中,以下代码与类型约束一起使用以确保"U"是 IEnumerable<T> .

public T DoSomething<U, T>(U arg) where U : IEnumerable<T>
{
    return arg.First();
}

我发现了一些允许添加多个类型约束的代码,例如:

public void test<T>(string a, T arg) where T: ParentClass, ChildClass 
{
    //do something
}

但是,此代码似乎强制 arg 必须是 ParentClass and ChildClass 的类型 . 我想做的是以下列方式说arg可能是一种 ParentClass or ChildClass

public void test<T>(string a, T arg) where T: string OR Exception
{
//do something
}

一如既往地感谢您的帮助!

3 回答

  • 6

    这是不可能的 . 但是,您可以为特定类型定义重载:

    public void test(string a, string arg);
    public void test(string a, Exception arg);
    

    如果它们是泛型类的一部分,则它们将优先于该方法的泛型版本 .

  • 52

    Botz答案100%正确,这里有一个简短的解释:

    当您编写方法(通用或非通用)并声明方法所采用的参数类型时,您将定义 Contract :

    如果你给我一个知道如何做类型T知道如何做的事情的对象,我可以提供'a':我声明的类型的返回值,或'b':某种行为,使用那种类型 .

    如果你尝试一次给它多个类型(通过拥有一个或)或者试图让它返回一个可能超过一种类型的值,那么 Contract 会变得模糊:

    如果你给我一个知道如何跳绳或知道如何计算pi到第15位的物体,我将返回一个可以钓鱼或混凝土的物体 .

    问题是,当你进入方法时,你不知道他们是否给了你 IJumpRopePiFactory . 此外,当你继续使用该方法时(假设你不确定你是否有 FisherAbstractConcreteMixer . 基本上它会让整个事情变得更加混乱 .

    您的问题的解决方案是两种可能性之一:

    • 定义多个定义每个可能的转换,行为或其他方法的方法 . 这是Botz的答案 . 在编程世界中,这被称为重载方法 .

    • 定义一个基类或接口,它知道如何完成方法所需的所有操作,并让一个方法只采用该类型 . 这可能涉及将 stringException 包装在一个小类中,以定义您计划如何将它们映射到实现,但随后一切都非常清晰且易于阅读 . 我可以在四年后来,阅读你的代码并轻松了解正在发生的事情 .

    您选择哪个取决于选择1和2的复杂程度以及它需要的可扩展性 .

    因此,对于您的具体情况,我会想象您只是从异常中提取消息或其他内容:

    public interface IHasMessage
    {
        string GetMessage();
    }
    
    public void test(string a, IHasMessage arg)
    {
        //Use message
    }
    

    现在您只需要将 stringException 转换为IHasMessage的方法 . 很容易 .

  • 24

    如果ChildClass意味着它是从ParentClass派生的,那么您可以编写以下内容来接受ParentClass和ChildClass;

    public void test<T>(string a, T arg) where T: ParentClass 
    {
        //do something
    }
    

    另一方面,如果要使用两种不同类型且它们之间没有继承关系,则应考虑实现相同接口的类型;

    public interface ICommonInterface
    {
        string SomeCommonProperty { get; set; }
    }
    
    public class AA : ICommonInterface
    {
        public string SomeCommonProperty
        {
            get;set;
        }
    }
    
    public class BB : ICommonInterface
    {
        public string SomeCommonProperty
        {
            get;
            set;
        }
    }
    

    然后你可以写你的通用函数;

    public void Test<T>(string a, T arg) where T : ICommonInterface
    {
        //do something
    }
    

相关问题