[英]c# Can I do this for “if”? or any other way to doing something like this?
[英]Is there any way to do something like this in C#?
有没有办法在C#中做这样的事情?
public void DoSomething(string parameterA, int parameterB)
{
}
var parameters = ("someValue", 5);
DoSomething(parameters);
关闭,但不幸只使用对象(所以你得到很多拳击/拆箱)
public void DoSomething(params object[] parameters)
{
}
var parameters = new object[]{"someValue", 5};
DoSomething(parameters); // this way works
DoSomething("someValue", 5); // so does this way
不是今天,不是。 我们目前正在为可能的假设未来版本的C#进行原型设计。
如果你能提供一个真正令人敬畏的理由,为什么你想要这个功能,这将是实际上从原型开始到可能的假设未来版本。 什么是你激动这个功能的令人敬畏的场景?
(请记住,Eric对C#可能假设的未来版本的推测仅用于娱乐目的,不应被解释为承诺将会有这样的版本,或者它将具有任何特定的功能集。)
如果您第一次存储为委托,则无需使用反射,但它确实需要强大的委托声明。
public void DoSomething(string parameterA, int parameterB)
{
Console.WriteLine(parameterA+" : "+parameterB);
}
void Main()
{
var parameters = new object[]{"someValue", 5};
Action<string,int> func=DoSomething;
func.DynamicInvoke(parameters);
}
...并且您可以忘记参数列表的编译时类型/健全性检查。 可能是一件坏事。
你可以通过反射来调用它,但这会产生一些开销:
using System;
using System.Reflection;
namespace SO2744885
{
class Program
{
public void DoSomething(string parameterA, int parameterB)
{
Console.Out.WriteLine(parameterA + ": " + parameterB);
}
static void Main(string[] args)
{
var parameters = new object[] { "someValue", 5 };
Program p = new Program();
MethodInfo mi = typeof(Program).GetMethod("DoSomething");
mi.Invoke(p, parameters);
}
}
}
当然,如果您可以更改方法签名以获取数组,那么它也会起作用,但在我看来这看起来会更糟糕。
不 - 这是不可能的。
也许这种方式更“干净”:
// standard method calling
DoSomething( "Johny", 5 );
// since C# 4.0 you can used "named parameters"
DoSomething( name: "Johny", number: 5 );
// calling with parameter's "container"
DoSomething( new DoSomethingParameters( "Johny", 5 ) );
// calling with parameter's "container"
DoSomething( new DoSomethingParameters{ Name = "Johny", Number = 5 } );
// calling with callback for parameters initialization
DoSomething( p => { p.Name = "Johny"; p.Number = 5; } );
// overload of DoSomething method with callback, which initialize parameters
public void DoSomething( Action<DoSomethingParameters> init ) {
var p = new DoSomethingParameters();
init( p );
DoSomething( p );
}
// overload of DoSomething method for calling with simple parameters
public void DoSomething( string name, int number ) {
var p = new DoSomethingParameters( name, number );
DoSomething( p );
}
// the "main executive" method which is "doing the work"
// all posible parameters are specified as members of DoSomethingParameters object
public void DoSomething( DoSomethingParameters p ) { /* ... */ }
// specify all parameters for DoSomething method
public class DoSomethingParameters {
public string Name;
public int Number;
public DoSomethingParameters() { }
public DoSomethingParameters( string name, int number ) {
this.Name = name;
this.Number = number;
}
}
灵感来自史蒂文的回答:
static public void Execute<T1, T2>(this Tuple<T1, T2> parameters, Action<T1, T2> action)
{
action(parameters.Item1, parameters.Item2);
}
var parameters = Tuple.Create("someValue", 5);
parameters.Execute(DoSomething);
我喜欢Henrik的答案,除了它强加了一些奇怪的语法:参数调用自己的方法。 我会反过来这样做。 这种方法的唯一问题是它使您明确地将方法强制转换为委托。
无论如何,这是基本的想法:
// wrapped code to prevent horizontal overflow
public static void Execute<T1, T2>
(this Action<T1, T2> action, Tuple<T1, T2> parameters) {
action(parameters.Item1, parameters.Item2);
}
等等(更多T
s)。
用法:
var parameters = Tuple.Create("Hi", 10);
Action<string, int> action = DoSomething;
action.Execute(parameters);
您还可以使用返回值轻松执行此操作:
// wrapped code to prevent horizontal overflow
public static TResult Return<T1, T2, TResult>
(this Func<T1, T2, TResult> func, Tuple<T1, T2> parameters) {
return func(parameters.Item1, parameters.Item2);
}
等等。
我还想指出,仅仅因为你不在.NET 4.0上,这并不意味着你不能轻易地实现你自己的Tuple<T1, T2, ...>
类型。
你可以这样做(.NET 4.0):
var parameters = Tuple.Create("someValue", 5);
DoSomething(parameters.Item1, parameter.Item2);
你可以做:
public void DoSomething(string parameterA, int parameterB)
{
}
var func = (Action)(() => DoSomething("someValue", 5));
func();
如果它们都是相同的类型,是的,你可以做一些这样的事情:
public void Print(params string[] args) {
foreach (string arg in args) {
Console.WriteLine(arg);
}
}
// ...
Print("apple", "banana");
Print("apple", "banana", "cherry");
Print("apple", "banana", "cherry", "doughnut");
否则,不,你不能在不使用反射的情况下扩展参数。 C#没有Ruby的splat运算符 。
如果您不想更改方法签名,为什么不使用适当的签名声明新方法并将其用作代理。 喜欢
public void DoSomething(string parameterA, int parameterB)
{
// Original do Something
}
public void DoSomething(object[] parameters)
{
// some contract check whether the parameters array has actually a good signature
DoSomething(parameters[0] as string,(parameters[1] as int?).Value);
}
var parameters = new object[]{"someValue", 5};
DoSomething(parameters);
你也可以尝试LinFu.Reflection提供的一些东西,比如Late Binding。 有了它你可以做这样的事情:
var dosomethingobject = new ObjectThatHasTheDoSomething();
DynamicObject dynamic = new DynamicObject(dosomethingobject);
var parameters = new object[]{"someValue", 5};
dynamic.Methods["DoSomething"](parameters);
为此,您需要DoSomething
方法位于对象内。
“var”只表示一种特定的类型,它是写入类型名称的有效简写。 在上面你没有指定任何类型。 唯一的方法是创建一个参数类来批量表示输入...
public void DoSomething(Parameters param)
{
...
}
var param = new Parameters("someValue", 5);
DoSomething(param);
......但这只会在特定情况下有用。 您可以使多个Parameters构造函数表示不同的参数排列,但您调用的函数只接受一个输入 - Parameters对象。 因此,你真的在破坏重载函数的能力。
所以,简而言之,没有。 =)
在.NET 4中如何(为了好奇)
public void DoSomething(string parameterA, int parameterB)
{
}
public void Helper(dynamic parameter)
{
DoSomething(parameter.Parameter1, parameter.Parameter2);
}
var parameters = new {Parameter1="lifeUniverseEverything", Parameter2=42};
Helper(parameters);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.