当方法传递的参数是值类型时,变量的栈数据会完整地复制到目标参数中即实参和形参中的数据相同但存放在内存的不同位置。所以,在目标方法中对形参所做的更改不会对调用者的初始变量产生任何影响。
当方法传递的参数是引用类型是,只是将变量的引用复制到目标参数中,实参和形参的引用指向内存中的同一位置。所以,在目标方法中对形参所做的更改会影响调用者的初始变量。
二、一些特殊的方法参数
1、引用参数---ref (使值类型的变量做方法参数时也可以传引用)
一些数据类型(例如类,数组等引用类型)作为方法的参数时默认是传引用的,大多数数据类型(例如结构,整数类型等值类型)在作为方法的参数时是传值的。那么,如何使值类型的数据作为方法参数时传递的也是引用呢?
方法很简单,只需要在形参的数据类型前加上关键字ref,并在调用时相应地实参前也加上关键字ref即可。
例如: void Swap( ref String first, ref String second) { }
String a="dddd",b="dbbb";
Swap(ref a,ref b); 注意:ref参数必须是可以赋值的变量
2、输出参数---out
除了将参数单向传入一个方法(传值),或同时将参数传入和传出一个方法(传引用)之外,还可以将数据从一个方法内部单向传出方法。为此,代码需要使用关键字out来修饰参数类型。
例如: int x; //
func(out x); //out参数必须是可以赋值的变量,在调用func方法前对out参数赋不赋值都可以。
void func(out int x ) {};// 在此方法中,在使用out参数x之前必须对其赋值,即使在调用此方法前已经对out参数x赋值了,在此方法中仍吧x看做未赋值的变量。
ref参数与out参数都是传引用,在方法中对参数所做的修改都会传到调用者。区别在于,out参数不接受调用者传来参数的数据值,而是把该参数当做未赋值的参数。
3、参数数组-----params(可以将相同类型,数量可变的多个参数传给一个方法)
引入:一般,参数的数量都是由目标方法声明所确定。然而,有时我们希望参数的数量是可变的。或许最好的方法是为方法传一个数组。然而,这会使调用代码变得稍微复杂一些,因为需要事先构造一个数组,再将这个数组作为参数来传递。 为了简化代码,c#提供了一个特殊的关键字,它允许在调用一个方法是提供数量可变的参数,而不是由方法事先固定好参数的数量。参数是以逗号分隔的,还是作为一个数组来传递的
注意事项:
@1、参数数组不一定是方法声明中的唯一参数。单数必须是最后一个参数。由于只有最后一个参数才可能是参数数组,所以方法最多只能有一个参数数组。
@2、调用者可以为参数数组指定0个参数,这会造成包含0个数据项的一个数组。也可以显示地使用一个数组,而不是以逗号分隔的参数列表,最终生成的CIL代码是一样的。
@3、参数数组是类型安全的------类型必须匹配与数组指定的类型。
@4、假如目标方法的实现要求一个最起码的参数数量,请在方法声明中显示指定必须提供的参数。这样一来,假如要求的参数遗失了,就会导致编译器报错,而不需要依赖于运行时错误处理。例如:使用int max (int first,params int[] operands)而不是int max(params int[] operands),确保至少有一个值传给方法max。
4、可选参数:
从c#40开始,增添了对可选参数的支持。声明方法是将常量赋给参数,以后调用方法是就不必每一个参数都指定,若不指定该参数则该参数为方法声明时指定的初始值。
例如:
void func(int x, int y=2) { ConsoleWrinteLine(x+y);}
func(3,2) 和func(3)的输出结果是相同的。
注意:
@1、可选参数一定放在所有必须的参数(没有默认值的参数)后面。可选参数的数量可以是多个。
@2、默认值必须是一个常量,或者说必须是编译时能确定的一个值。
5、命名参数
命名参数是c#40新增的一个方法调用功能。利用命名参数,调用者可显示指定参数名,并为该参数赋一个值而不是像以前那样只能依据参数顺序来决定哪个值赋给哪个参数。
例如: void func(int x, int y=2) { ConsoleWrinteLine(x+y);} func(y:3,x:2);
void display(string firstname, string middlename=default(string), string lastname =default(string)); display(firstname:"susan",lastname: "lili");
注意:如果一个方法有大量参数,而且其中许多都是可选参数(访问Microsoft COM库时,这是很常见的情况),那么命名参数语法肯定能带来不少便利。但这个便利的代价是牺牲方法接口的灵活性。过去,参数名可以自由更改,不会造成调用代码无法编译。但在添加了命名参数后,参数名就成为方法接口的一部分。更改名称会导致使用命名参数的代码无法编译。
6、方法解析(即当同一个方法调用可以适用多个方法,将调用哪个方法)
当同时使用参数数组,可选参数,命名参数,方法重载等功能时,可能造成同一个方法调用可以适用多个方法。
(1)假如由于一个方法有一个可选参数,造成两个方法都适用(方法重载时可能出现),编译器最终选择的将使无可选参数的方法。
(2)假如有两个适用的方法,每个都需要(对参数)执行一次隐式转换,就选择与更具体的类型匹配的方法。例如,如果调用者传递的是一个int,那么接受double的方法将优先于接受object的方法。这是由于double比object更具体。
(3)如果有多个适用的方法,但无法从中挑选一个最具唯一性的,编译器就会报错,指明调用存在歧义。
好科幻啊!!你想做什么啊?
存储过程在C#中是以字符串的形式来表现的,怎么可能 啊,
再说了 C#中根本没有存储过程类型的定义,只有早SQL中才有的,两个不同的语言不可能的,除非你去数据库中查询!!
但是这个又是多此一举的做法!!
select name as 参数名称,xusertype 参数数据类型,length 参数数据长度 from syscolumns where id =(select id from sysobjects where name='存储过程名称')
这个查询出来全部是字符串的,你还要自己去解析成C#中的对应的数据类型,然后你对它又怎么赋值呢?
C#调用存储过程的是要先给参数赋值的,也就是说要知道参数类型然后在对应的赋值的,难不成你想动态获取,动态赋值,这个好像不现实哦!!同学。这个是好神费力的事情 啊!!
/
获取一个函数的依赖
@param string|callable $func
@param array $param 调用方法时所需参数 形参名就是key值
@return array 返回方法调用所需依赖
/
function getFucntionParameter($func,$param=[]) {
if(!is_array($param)) {
$param = [$param];
}
$ReflectionFunc = new \ReflectionFunction($func);
$depend = array();
foreach($ReflectionFunc->getParameters() as $value) {
if(isset($param[$value->name])) {
$depend[] = $param[$value->name];
}elseif($value->isDefaultValueAvailable()){
$depend[] = $value->getDefaultValue();
}else{
$tmp = $value->getClass();
if(is_null($tmp)) {
throw new \Exception("Function parameters can not be getClass {$class}");
}
$depend[] = $this->get($tmp->getName());
}
}
return $depend;
}
function test($a,$b=20) {
echo $a,',',$b;
}
$depend = getFucntionParameter('test',['a'=>30,'b'=>40]);
call_user_func_array('test',$depend); // 30,40
上面的函数是我开发的框架的容器的方法。
php提供了很完整的反射机制。不但可以反射函数,还可以反射方法,反射类构造函数。
private static boolean validParams(Object objects) {
for (Object obj : objects) {
Class clz = objgetClass();
Systemoutprintln(clz);
}
return false;
}
public static string GetMethodName()
{
var method = new StackFrame(1)GetMethod(); // 这里忽略1层堆栈,也就忽略了当前方法GetMethodName,这样拿到的就正好是外部调用GetMethodName的方法信息
var property = (
from p in methodDeclaringTypeGetProperties(
BindingFlagsInstance |
BindingFlagsStatic |
BindingFlagsPublic |
BindingFlagsNonPublic)
where pGetGetMethod(true) == method || pGetSetMethod(true) == method
select p)FirstOrDefault();
return property == null methodName : propertyName;
}
补充:其他方法
得到函数名:
SystemDiagnosticsStackTrace st = new SystemDiagnosticsStackTrace();
thisText = stGetFrame(0)ToString();
得到代码行,源代码文件名:
StackTrace st = new StackTrace(new StackFrame(true));
ConsoleWriteLine(" Stack trace for current level: {0}", stToString());
StackFrame sf = stGetFrame(0);
ConsoleWriteLine(" File: {0}", sfGetFileName());
ConsoleWriteLine(" Method: {0}", sfGetMethod()Name);
ConsoleWriteLine(" Line Number: {0}", sfGetFileLineNumber());
ConsoleWriteLine(" Column Number: {0}", sfGetFileColumnNumber());
以上就是关于c#如何获取当前调用传入的参数名称全部的内容,包括:c#如何获取当前调用传入的参数名称、c# 获取存储过程参数名和类型、php有没有什么函数可以获取一个方法中的参数名和参数类型的等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)