.NET 帮助

C# 引用关键字(开发人员工作原理)

Chipego
奇佩戈-卡琳达
2023年十一月13日
分享:

C# ref 关键字 是每个初学者都应该了解的重要工具。 它用于通过引用而不是值来传递参数或 args,允许在被调用方法内部对引用类型变量所做的更改反映到外部。 在本教程中,我们将详细介绍**ref关键字,并探索各种控制台代码示例以说明其工作原理。

ref 关键字介绍

在 C# 中传递方法参数时,默认情况下是按值传递的。 这意味着会创建参数值的副本,在调用方法中进行的任何更改都不会影响方法外的原始变量。 ref 关键字改变了这种行为,使您可以通过引用传递参数。 当参数通过引用传递时,方法内的任何更改都会直接影响方法外的原始变量。

关键概念

  • ref 关键字:用于指示变量通过引用传递。
  • 引用变量:引用数据存储位置的类型。
  • 值类型:保存实际数据的类型。
  • 原始变量:在使用ref关键字时,方法外的变量会反映在方法内部所做的更改。

引用传递

让我们先来了解一下变量如何通过引用传递的概念。 想象一下,您有一个递增整数的方法,如以下代码所示:

class Program
{
//method returns incremented value
    static void IncrementByOne(int num)
    {
        num++;
    }

    static void Main()
    {
        int value = 5;
        IncrementByOne(value);
        Console.WriteLine(value);  // Output: 5
    }
}
class Program
{
//method returns incremented value
    static void IncrementByOne(int num)
    {
        num++;
    }

    static void Main()
    {
        int value = 5;
        IncrementByOne(value);
        Console.WriteLine(value);  // Output: 5
    }
}
Friend Class Program
'method returns incremented value
	Private Shared Sub IncrementByOne(ByVal num As Integer)
		num += 1
	End Sub

	Shared Sub Main()
		Dim value As Integer = 5
		IncrementByOne(value)
		Console.WriteLine(value) ' Output: 5
	End Sub
End Class
$vbLabelText   $csharpLabel

在上面的代码中,即使我们在IncrementByOne方法中增加了num,原始value仍然保持不变。 这是因为num是原始变量的副本,对其进行的更改不会影响原始变量。

使用 ref 关键字

现在,让我们看看ref关键字如何改变这种行为。 通过使用ref,您可以通过引用将变量传递给方法,如下面的代码示例之一所示。

class Program
{
//ref int
    static void IncrementByOneRef(ref int num)
    {
        num++;
    }

    static void Main()
    {
        int value = 5;
        IncrementByOneRef(ref value);
        Console.WriteLine(value);  // Output: 6
    }
}
class Program
{
//ref int
    static void IncrementByOneRef(ref int num)
    {
        num++;
    }

    static void Main()
    {
        int value = 5;
        IncrementByOneRef(ref value);
        Console.WriteLine(value);  // Output: 6
    }
}
Friend Class Program
'ref int
	Private Shared Sub IncrementByOneRef(ByRef num As Integer)
		num += 1
	End Sub

	Shared Sub Main()
		Dim value As Integer = 5
		IncrementByOneRef(value)
		Console.WriteLine(value) ' Output: 6
	End Sub
End Class
$vbLabelText   $csharpLabel

注意在方法签名和调用中都有ref关键字。 这告诉C#您想通过引用传递value变量。 因此,在IncrementByOneRef方法中所做的更改会反映在原始value变量中。

使用值类型

ref关键字在处理整数、双精度数和结构体等类型时特别有用。 这些类型直接存储在内存中,通过引用传递它们可以提高性能,并对数据操作进行更精确的控制。

修改引用变量

虽然ref关键字通常与值类型相关联,但它也可以用于引用类型变量。 引用类型(如类和数组)存储的是对内存中实际数据的引用,而不是数据本身。 这意味着您要处理的是指针式结构,通过引用传递会产生不同的结果,如下例所示:

class Person
{
    public string Name { get; set; }
}

class Program
{
    //method
    static void ChangeName(ref Person person)
    {
        //new object
        person = new Person { Name = "Alice" };
    }

    static void Main()
    {
        Person person = new Person { Name = "Bob" };
        ChangeName(ref person);
        Console.WriteLine(person.Name);  // Output: Alice
    }
}
class Person
{
    public string Name { get; set; }
}

class Program
{
    //method
    static void ChangeName(ref Person person)
    {
        //new object
        person = new Person { Name = "Alice" };
    }

    static void Main()
    {
        Person person = new Person { Name = "Bob" };
        ChangeName(ref person);
        Console.WriteLine(person.Name);  // Output: Alice
    }
}
Friend Class Person
	Public Property Name() As String
End Class

Friend Class Program
	'method
	Private Shared Sub ChangeName(ByRef person As Person)
		'new object
		person = New Person With {.Name = "Alice"}
	End Sub

	Shared Sub Main()
		Dim person As New Person With {.Name = "Bob"}
		ChangeName(person)
		Console.WriteLine(person.Name) ' Output: Alice
	End Sub
End Class
$vbLabelText   $csharpLabel

在此示例中,ChangeName 方法将 person 变量的引用更改为一个新的 Person 对象。 因此,原始person变量现在指向一个不同的对象,其名称为“Alice”。

使用引用类型参数的方法重载

您可以有多个名称相同但参数不同的方法。 这就是所谓的方法重载。 当使用ref关键字时,方法重载功能变得更强大。

class Calculator
{
    public static void Add(ref int x, int y)
    {
        x += y;
    }

    public static void Add(ref double x, double y)
    {
        x += y;
    }
}

class Program
{
    static void Main()
    {
        int intValue = 5;
        double doubleValue = 7.5;
        //ref parameter
        Calculator.Add(ref intValue, 3);
        Calculator.Add(ref doubleValue, 2.5);

        Console.WriteLine(intValue);      // Output: 8
        Console.WriteLine(doubleValue);   // Output: 10.0
    }
}
class Calculator
{
    public static void Add(ref int x, int y)
    {
        x += y;
    }

    public static void Add(ref double x, double y)
    {
        x += y;
    }
}

class Program
{
    static void Main()
    {
        int intValue = 5;
        double doubleValue = 7.5;
        //ref parameter
        Calculator.Add(ref intValue, 3);
        Calculator.Add(ref doubleValue, 2.5);

        Console.WriteLine(intValue);      // Output: 8
        Console.WriteLine(doubleValue);   // Output: 10.0
    }
}
Friend Class Calculator
	Public Shared Sub Add(ByRef x As Integer, ByVal y As Integer)
		x += y
	End Sub

	Public Shared Sub Add(ByRef x As Double, ByVal y As Double)
		x += y
	End Sub
End Class

Friend Class Program
	Shared Sub Main()
		Dim intValue As Integer = 5
		Dim doubleValue As Double = 7.5
		'ref parameter
		Calculator.Add(intValue, 3)
		Calculator.Add(doubleValue, 2.5)

		Console.WriteLine(intValue) ' Output: 8
		Console.WriteLine(doubleValue) ' Output: 10.0
	End Sub
End Class
$vbLabelText   $csharpLabel

在上面的示例中,我们重载了Add方法,使其能够与intdouble类型一起工作。ref关键字允许方法直接修改原始变量。

使用 out 关键字

另一个相关的关键词是out。 它类似于ref,但用途略有不同。 虽然ref要求变量在传递之前被初始化,out关键字用于当你希望一个方法给一个不一定有初始值的参数赋值时使用:

class Program
{
    static void Divide(int dividend, int divisor, out int quotient)
    {
        quotient = dividend / divisor;
    }

    static void Main()
    {
        int result;
        Divide(10, 2, out result);
        Console.WriteLine(result);  // Output: 5
    }
}
class Program
{
    static void Divide(int dividend, int divisor, out int quotient)
    {
        quotient = dividend / divisor;
    }

    static void Main()
    {
        int result;
        Divide(10, 2, out result);
        Console.WriteLine(result);  // Output: 5
    }
}
Friend Class Program
	Private Shared Sub Divide(ByVal dividend As Integer, ByVal divisor As Integer, ByRef quotient As Integer)
		quotient = dividend \ divisor
	End Sub

	Shared Sub Main()
		Dim result As Integer = Nothing
		Divide(10, 2, result)
		Console.WriteLine(result) ' Output: 5
	End Sub
End Class
$vbLabelText   $csharpLabel

在此示例中,Divide 方法计算商,并使用 out 关键字将其赋值给 quotient 变量。 值得注意的是,在将result传递给方法之前,您不需要初始化它。

ref 和 out 关键字的区别

out 关键字与 ref 关键字相似,但有明显不同。 out 参数不需要初始值,而 ref 参数在方法调用之前必须有初始值。

潜在陷阱

虽然refout关键字可以是强大的工具,但应谨慎使用。 不正确地使用这些关键词会导致代码混乱和意外行为。 例如,如果不先进行初始化,您无法在 refout 参数中使用非 ref 变量,因为这将导致编译错误。

ref 关键字的高级用法

使用引用类型和值类型

了解两个引用类型和值类型之间的区别在使用ref关键字时至关重要。

  • 引用类型:变量指的是存储数据的内存位置,例如,对象、数组等。
  • 值类型:变量直接包含数据,例如,整数、浮点数等。

    使用ref与值类型一起可以使更改在方法外反映出来,而引用类型变量本质上就是这种行为。

带有 ref 关键字的扩展方法

您还可以在扩展方法中使用ref关键字。 举例说明:

public static class StringExtensions
{
//example
    public static void AppendValue(ref this string input, string value)
    {
        input += value;
    }
}
public static class StringExtensions
{
//example
    public static void AppendValue(ref this string input, string value)
    {
        input += value;
    }
}
Public Module StringExtensions
'example
	Public Sub AppendValue(ByRef Me input As String, ByVal value As String)
		input &= value
	End Sub
End Module
$vbLabelText   $csharpLabel

编译器错误和 ref 关键字

如果您忘记在方法签名或方法调用中包含ref关键字,将会导致编译时出现编译器错误。

异步 方法和 ref 参数

请注意,您不能在迭代器方法或async方法中使用ref参数,因为这些方法要求按值传递参数。

介绍 Iron Suite

除了理解如 C# 中 ref 关键字等关键概念外,还有一套强大的工具可以使开发人员的生活更加轻松。 Iron Suite 是一系列强大的工具和库,包括 IronPdf、IronXL、IronOCR 和 IronBarcode。 让我们一起来探索这些工具,看看它们如何在没有任何争论的情况下提升您的编码体验。

IronPDF PDF 处理轻松搞定

了解 IronPDF 作为 Iron Suite 的重要组成部分。它是一个库,允许开发人员在 C# 中创建、读取和编辑 PDF 文件。 如果您想将 HTML 转换为 PDF,IronPDF 有您需要的工具。 请查看HTML 转换为 PDF 的教程以了解更多关于此功能的详细信息。

IronXL.Excel 操作尽在指尖

在 C# 中处理 Excel 文件可能具有挑战性,但IronXL 功能简化了这一任务。 它使您无需安装 Excel 即可读取、编写、编辑和处理 Excel 文件。 从导入数据到创建新的电子表格,IronXL.Excel 都能用 C# 处理。

IronOCR 用于 C# 的光学字符识别

光学字符识别 (OCR) 可能很复杂,但发现 IronOCR可以简化此过程。 使用该库,您可以读取图像中的文本并将其转换为机器可读文本。 无论您需要从扫描文档中提取文本,还是从图像中识别字符,IronOCR 都能提供帮助。

IronBarcode 条形码生成和读取

条形码广泛应用于各个行业,现在在您的应用程序中处理条形码,使用 IronBarcode library 变得更加容易。 该库可让您在 C# 中创建、读取和处理 BarCode。 IronBarcode 支持多种 QR 和 BarCode 格式。

Iron Suite 与 ref 关键字的关系

您可能想知道这些工具与我们讨论过的ref关键字有何关联。 在处理涉及PDF、Excel、OCR或条形码的复杂项目时,有效使用ref关键字和其他C#原则对于高效管理代码至关重要。

例如,在使用 IronXL 操作大型 Excel 文件时,使用 ref 关键字按引用传递对象可以使您的代码更高效和易于维护。 同样,使用IronPDF处理PDF文档可能涉及使用ref关键字的方法。

了解核心语言特性如ref关键字,并能够使用Iron Suite等工具,为您提供强大的组合,帮助您构建高效、稳健且多功能的应用程序。 Iron Suite 可与您现有的 C# 知识无缝结合,共同帮助您创建更专业、更复杂的解决方案。

结论

C# 语言凭借 ref 关键字等特性,为开发人员提供了强大的功能。 与 Iron Suite(包括 IronPDF、IronXL、IronOCR 和 IronBarcode)结合使用,可能性会变得更加广阔。

Iron Suite 中的每款产品都提供Iron Suite 免费试用,让您无需立即投资即可探索和使用其广泛的功能。 如果您决定继续购买完整许可证,单个组件的定价从$749开始。

如果您觉得整个 Iron Suite 符合您的需求,还有一笔极好的交易在等着您。 您只需支付两个单独组件的价格,即可获得全套组件。

Chipego
软件工程师
Chipego 拥有出色的倾听技巧,这帮助他理解客户问题并提供智能解决方案。他在 2023 年加入 Iron Software 团队,此前他获得了信息技术学士学位。IronPDF 和 IronOCR 是 Chipego 主要专注的两个产品,但他对所有产品的了解每天都在增长,因为他不断找到支持客户的新方法。他喜欢 Iron Software 的合作氛围,公司各地的团队成员贡献他们丰富的经验,以提供有效的创新解决方案。当 Chipego 离开办公桌时,你经常可以发现他在看书或踢足球。
< 前一页
C# Datatable 转 List(开发者如何使用)
下一步 >
NLog C#(适用于开发人员的工作原理)