如何从同一函数返回不同类型的对象 [英] How do I return objects of different types from the same function

查看:91
本文介绍了如何从同一函数返回不同类型的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在以下函数中重用代码以返回不同类型的对象?



How do I reuse code in the following functions to return objects of different types?

public A Execute(object parameters)
{
    using (var x = X.Create(parameters))
    {
        Process(x);
        return Func1(x);
    }
}

public B Execute(object parameters)
{
    using (var x = X.Create(parameters))
    {
        Process(x);
        return Func2(x);
    }
}





Func1和Func2是具有不同返回类型的两个不同函数。我觉得可以在这里使用策略模式的一些改编,但我不确定是什么。



Func1 and Func2 are two different functions with different return types. I feel like some adaptation of the strategy pattern can be used here but I'm not sure what.

推荐答案

你不能在同一个类中只有方法它们的返回类型不同。



我可以在这里想到两种代码重用方法,都要求将Execute(..)作为通用方法。



1)如果你可以用通用的Func< T>替换Func1和Func2。 :

You can't have methods in the same class that only differ by their return type.

I can think of two ways for code-reuse here, both requiring making Execute(..) a generic method.

1) If you can replace Func1 and Func2 by a generic Func<T> :
public T Execute<T>(object parameters)
{
    using (var x = X.Create(parameters))
    {
        Process(x);
        return Func<T>(x);
    }
}





2)如果没有,请将Func1或Func2作为代表传递:



2) If not, pass Func1 or Func2 as a delegate:

// "..." stands for the static type name of the "x" below:
public T Execute<T>(object parameters, Func<..., T> func) 
{
    using (var x = X.Create(parameters))
    {
        Process(x);
        return func(x);
    }
}





编辑:

如果您打算创建一个返回类型为A或B的对象的工厂方法,则取决于参数的值,和A和B派生自公共基类(我在这里称之为A0)然后这样的事情会没事的:




If your intention is to create a factory-method that returns either an object of type A or B, depending on the value of parameters, and A and B derive from a common base class (I'll call it A0 here) then something like this would be alright:

public A0 Execute(object parameters)
{
    using (var x = X.Create(parameters))
    {
        Process(x);

        if (parameters == indicate_you_want_A)
            return Func1(x);
        else if (parameters == indicate_you_want_B)
            return Func2(x);
        else
            throw new NotSupportedException("meaningful message here");
    }
}


下面是一个静态泛型类的示例,它将返回新类的实例,其中内部数据类型由新类被约束为结构。我相信这个例子演示了在C#中实现Factory Class模式的通常特性:使用接口;通用约束等
Here's an example of a static generic Class that will return instances of new Classes where the internal data type used by the new Class is constrained to be a struct. I believe this example demonstrates the "usual" features of implementing the Factory Class pattern in C#: use of an interface; generic constraints, etc.
using System;

namespace StructClassFactoryDemo
{
    // see Note #1
    internal interface IGenericStruct<T> where T : struct
    {
        T[] Parameters { set; get; }

        void Execute(Func<T,T> paramFunc, T[] parameters);
    }

    internal static class GenericStructFactory<T> where T : struct
    {
        internal static GenericStructClass<T> Create(Func<T,T> paramFunc, params T[] parameters)
        {
            GenericStructClass<T> newT = new GenericStructClass<T>();

            if (paramFunc != null) newT.Execute(paramFunc, parameters);

            Console.WriteLine("created {0} type",  typeof(T).Name);

            return newT;
        }
    }

    public class GenericStructClass<T> : IGenericStruct<T> where T : struct
    {
        public T[] Parameters { set; get; }

        public void Execute(Func<T,T> paramFunc, T[] parameters)
        {
            if (parameters == null) return;

            // see Note #2
            if (typeof(T).IsValueType && paramFunc != null)
            {
                for (int i = 0; i < parameters.Length; i++)
                {
                    parameters[i] = paramFunc(parameters[i]);
                }
            }

            Parameters = parameters;
        }
    }
}

以下是在某些类中使用此工厂的方法:

Here's how you might use this Factory in some Class:

// predefined integer function
Func<int,int> intFunc = (x) =>
{
    return x + 100;
};

// predefined double function
Func<double, double> doubleFunc = (x) =>
{
    return x + 43.024;
};

// function parameter defined as 'null
GenericStructClass<int> ClassA0 = GenericStructFactory<int>
    .Create(
    null,
    new int[] { 1, 2, 3, 4, 5, 6 });

// using predefined integer function
GenericStructClass<int> ClassA1 = GenericStructFactory<int>
    .Create(
    intFunc,
    new int[] { 1, 2, 3, 4, 5, 6 });

// using predefined double function
GenericStructClass<double> ClassA2 = GenericStructFactory<double>
    .Create(
    doubleFunc,
    new double[] { 1.24, 2.23, 3.5, 4.9, 5.1, 6.2 });

// using an in-line lambda expression that returns a 'long for the function
GenericStructClass<long> ClassA3 = GenericStructFactory<long>
    .Create(
    x => x + 23,
    new long[] { 1, 2, 3, 4, 5, 6 });

// using an in-line lambda expression that returns a 'DateTime for the function
GenericStructClass<DateTime> ClassA4 = GenericStructFactory<DateTime>
    .Create(
    dt => dt.AddDays(100),
    new DateTime[]
    {
        DateTime.Now, DateTime.Now.AddDays(1), DateTime.Now.AddDays(2)
    });

注意:



1.即使在这里实现了一个接口,所显示的代码实际上并没有以特定的方式证明它的使用;那么,为什么呢? :imho,通常情况是你想要扩展 Factory类,并且你将使用显示的接口来定义另一个将用作'GenericStructClass的替代类的Class。此外,imho,最好在开发中使用Interfaces来强制执行纪律。



2.注意你不能使用'ValueType作为约束在通用类中,但您可以使用'Struct,并且,在通用类中,您可以测试通用类型是否为'ValueType,如此处所示。

Notes:

1. even though an Interface is implemented here, the code shown really does not demonstrate its use in a specific way; so, why's it there ? : imho, it is often the case that you will want to extend a Factory class, and you would use the Interface shown to define another Class that would be used as an alternative to 'GenericStructClass. Further, imho, it is a good idea to use Interfaces to "enforce discipline" in development.

2. Note that you can't use 'ValueType as a constraint in a Generic Class, but you can use 'Struct, and, within a Generic Class, you can test to see if the Generic Type is a 'ValueType, as shown here.


这篇关于如何从同一函数返回不同类型的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆