如何从同一函数返回不同类型的对象 [英] How do I return objects of different types from the same function
问题描述
如何在以下函数中重用代码以返回不同类型的对象?
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屋!