ref问题,请讲解

    在本文之前有2篇介绍Ref和Out的文章,同学看后提出了以下问题

public static void ValueParam(string str)
{
   str = "251";
}
public static void RefParam(ref string str)
{
   str = "250";
}
public static void Main()
{
   string str = "249";
   ValueParam(str);
   Console.WriteLine(" Value Param:"+str);
   RefParam(ref str);
   Console.WriteLine(" Ref Param:"+str);
}
结果为:
Value Param:249  //这里结果为249和下面程序的b我就混淆搞不清楚了
Ref Param:250    //250我能理解

------------------------------------------------------------
public class MyClass 
{
  public static void TestRef(ref char i) 
  {

    i =  'b ';
  }
   
  public static void TestNoRef(char i) 
  {
    
    i =  'c ';
  }
   

  public static void Main() 
  { 
    char i =  'a ';    
    TestRef(ref i);  
    Console.WriteLine(i);
    TestNoRef(i);
    Console.WriteLine(i);
  }
}

  大家很容易看出输出结果是: 

b   //我也能理解
b   //这里用的是TestNoRef(i)为什么输出也是b呢?如果按上一个程序的思想结果应该是a才是啊 

==================================================================================

之所以出现上面的问题我想他是对C#的值传递和引用传递没有很好的搞清楚。

ref就是传递了引用,所以修改会被保存下来 
或者说
by ref 就是将参数的指针传给函数, 结果就是参数会被函数修改并且保存下来,影响下面要使用这参数的值
by val 就是传一个值的copy , 原参数在这次使用后不会被修改。讲到这我想大家应该可以明白了

程序部分讲解如下:

   string str = "249";                  //str="249"
   ValueParam(str);                //str="249",因为是by value的,所以str的引用不变,str的引用的还是之前的"249"对象
   Console.WriteLine(" Value Param:"+str);    //str="249"
   RefParam(ref str);                         //str="250",因为是by ref的,所以str的引用修改变成引用"250"对象
   Console.WriteLine(" Ref Param:"+str);      //str="250"

    char i =   'a  ';           //i= 'a '
    TestRef(ref i);           //i= 'b ',因为是by ref的,所以i的值修改了
    Console.WriteLine(i);     //i= 'b '
    TestNoRef(i);             //i= 'b ',因为是by value的,所以i不变,i的值还是之前的 'b '
    Console.WriteLine(i);     //i= 'b '


 

<think>嗯,用户让我介绍一下C#的方法,我需要仔细考虑怎么组织内容。首先,得确定用户的基础,可能是有一定编程经验但刚接触C#的人,或者是完全的新手?需要覆盖基本概念,同时不要太简单。 先想方法的基本结构,比如访问修饰符、返回类型、方法名、参数这些组成部分。用户可能想知道如何定义一个方法,所以需要例子说明。比如public void MyMethod(int param)这样的结构。 然后,参数传递方式,值类型和引用类型的区别,还有ref和out关键字。这里可能需要举例说明,比如交换两个变量的方法,用ref的情况。另外,out和ref的不同,比如需要在方法内赋值,适合返回多个值的情况。 方法重载也是重要部分,同一个方法名不同参数列表。需要举例子,比如Add方法的不同版本,参数个数或类型不同。 接下来,可选参数和命名参数,这可以让方法调用更灵活。比如设置默认值,调用时指定参数名,这样代码更清晰。 Lambda表达式和匿名方法,这部分属于进阶内容,但C#使用广泛,特别是LINQ。需要简单示例,比如Func委托和Lambda的写法。 异常处理,虽然主要是try-catch,但方法中抛出异常也是关键点。比如参数验证时抛出ArgumentException,告诉用户正确的错误处理方式。 静态方法和实例方法的区别,什么时候用静态。比如工具类方法适合静态,而需要对象状态的方法用实例。 扩展方法,这个特性很重要,可以给现有类型添加方法而不修改源码。比如为string添加IsNumeric方法,演示如何定义和使用。 异步方法,async和await关键字,现代编程中处理异步操作必不可少。需要简单例子,比如调用网络求时如何不阻塞线程。 最后,方法设计的最佳实践,比如单一职责、合理命名、参数数量控制、异常处理等,这些是写出高质量代码的关键。 需要考虑用户可能的疑问,比如参数传递的细节,ref和out的使用场景,或者异步方法的基础概念是否需要深入。可能需要平衡深度和广度,避免信息过载,但又要足够详细。 结构上应该分点讲解,每个部分用标题,配合代码示例。确保使用正确的中文术语,比如“形参”、“实参”、“重载”等。代码示例要符合C#的语法规范,比如正确的修饰符和大括号使用。 可能还需要提醒一些常见错误,比如忘记返回类型,参数默认值的位置,或者ref/out的使用限制。但用户的问题主要是介绍,可能不需要太多错误示例,重点在正确用法。 总之,要层次分明,从基础到高级,逐步展开,确保用户能跟随并理解各个概念。同时,保持语言简洁,例子明确,帮助用户建立对C#方法的全面认识。</think>好的,我将分步骤为您系统讲解C#方法的核心知识,并配合代码示例说明: ### 一、方法的基本结构 ```csharp 访问修饰符 返回类型 方法名(参数列表) { // 方法体 return 返回值; // 非void类型必须包含 } ``` 示例: ```csharp public int Add(int a, int b) { return a + b; } ``` ### 二、参数传递方式 1. **值类型参数**(默认): ```csharp void Modify(int num) { num = 10; } // 调用后原始值不变 ``` 2. **引用类型参数**(ref/out): ```csharp void Swap(ref int x, ref int y) { int temp = x; x = y; y = temp; } ``` 3. **输出参数**(out): ```csharp bool TryParse(string s, out int result) { return int.TryParse(s, out result); } ``` ### 三、方法重载(Overloading) ```csharp public int Add(int a, int b) => a + b; public double Add(double a, double b) => a + b; public int Add(int a, int b, int c) => a + b + c; ``` ### 四、可选参数与命名参数 ```csharp void PrintMessage(string message, bool uppercase = false) { Console.WriteLine(uppercase ? message.ToUpper() : message); } // 调用示例 PrintMessage("Hello"); // 使用默认参数 PrintMessage("Hello", true); // 指定参数 PrintMessage(uppercase: true, message: "Hi"); // 命名参数 ``` ### 五、Lambda表达式(C# 3.0+) ```csharp Func<int, int> square = x => x * x; Action<string> log = msg => Console.WriteLine($"[LOG] {msg}"); ``` ### 六、异常处理 ```csharp public double Divide(int dividend, int divisor) { if (divisor == 0) throw new ArgumentException("Divisor cannot be zero"); return (double)dividend / divisor; } ``` ### 七、静态方法 vs 实例方法 ```csharp // 静态方法(类级别) public static class MathUtils { public static int Factorial(int n) { /* ... */ } } // 实例方法(对象级别) public class Calculator { public int Add(int a, int b) => a + b; } ``` ### 八、扩展方法(C# 3.0+) ```csharp public static class StringExtensions { public static bool IsNumeric(this string str) { return double.TryParse(str, out _); } } // 使用 string input = "123"; bool isNum = input.IsNumeric(); ``` ### 九、异步方法(C# 5.0+) ```csharp public async Task<string> FetchDataAsync() { using HttpClient client = new(); return await client.GetStringAsync("https://api.example.com/data"); } ``` ### 十、最佳实践原则 1. **单一职责原则**:每个方法只完成一个明确的任务 2. **命名规范**:使用动词短语(GetUser、CalculateTotal) 3. **参数控制**:建议不超过5个参数,过多时考虑参数对象 4. **异常处理**:在方法入口验证参数有效性 5. **文档注释**:使用XML注释说明方法用途 ```csharp /// <summary> /// 计算两个整数的和 /// </summary> /// <param name="a">第一个加数</param> /// <param name="b">第二个加数</param> /// <returns>两个参数的和</returns> public int Add(int a, int b) => a + b; ``` 理解这些核心概念后,您可以通过以下方式进一步优化方法设计: - 使用泛型方法提高复用性 - 合理应用委托和事件 - 掌握表达式树方法 - 利用本地函数(C# 7.0+)组织复杂逻辑 需要具体某个特性的深入讲解或实际应用场景分析吗?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值