Unity C# 爆破计划五:方法与权限

文章目录


五、方法与权限

Covers:方法和函数

访问权限

尽管还没有正式开始讲 C# 的类,但我们已经写过一个类 class Program 了,并且向其中添加了一个方法 static void Main。

C# 中一切都是对象,因此一切函数都是方法;方法就是封装在类或结构中的函数;封装就是把函数和数据打个包(这个包就是类或者结构);而言及封装就涉及到访问权限,因此我们需要先了解 C# 对访问权限的定义。

C# 中有 5 种访问权限:

  1. private:只有本类内可见,私有的;
  2. protected:只有本类,以及从本类派生出的子类内可见;
  3. internal:只在本程序集内可见,这包括了本类、本类在本程序及内派生出的子类、本程序集内其他类;
  4. protected internal:在本程序集内,以及其它程序集中从本类派生出的子类中都可见;
  5. public:在任何作用域中都可以访问,公有的。

这些访问权限都可以修饰方法或者属性,也可以修饰类本身,当指定一个类的访问权限时,就是指定该类对于其他类的可见性,类的访问权限默认是 internal 的

定义方法

定义一个方法的语法是:ACCESS MODIFIER RET_TYPE METHOD(PARAMS) {BODY},这包含 5 个信息:

  • 这是名为 METHOD 的方法;
  • 其返回值的类型为 RET_TYPE(不返回任何值时为 void);
  • 接受形参表 PARAMS 规定的参数(不接受参数时就省略);
  • 该函数的访问权限是 ACCESS(可省略,默认为 private);
  • MODIFIER 是额外的修饰符,如 static(可省略,但目前我们编写的方法都需要这个修饰符);
  • 函数执行体为 BODY,用 return 关键字返回值,一旦程序抵达一个 return,后面的代码就不会继续执行。

参数传递

常常要向函数中传递参数,形参表规定了参数的类型、传入顺序和方式。传参方式有 3 种:值传参引用传参输出传参

  • 值传参:直接把调用处给出的参数拷贝一份传入,在方法执行体中修改传入的参数时对调用方不会产生任何影响,语法是 TYPE PARAM,指定一个类型为 TYPE 的参数 PARAM,以值传递;

  • 引用传参:传入一个指向调用处所给实际参数变量的引用,在执行体中修改传入的参数时,会直接修改调用处的对应变量,行为与 C++ 一致,语法是 ref TYPE PARAM,而且 在调用处,为这个形参传递的实参必须是变量,且变量名前面也要加上 ref 关键字

  • 输出传参:与引用传参类似,但实际参数可以是未初始化的,用于实现多返回值,语法是 out TYPE PARAM,且变量名前面也要加上 out 关键字

    解释:有时我们希望方法返回多个值,那么在调用处就需要用额外的变量来接收这些值,C# 把这样的变量也作为参数用引用的形式传入,此时这些变量在调用前拥有的值是没有意义的,我们会想要用定义过而未初始化的变量来作为这样的参数。C# 中不存在先声明后定义,而将定义过(拥有内存资源)却未初始化的变量以引用传参传递给函数会造成安全问题,为解决这个矛盾,C# 提供了输出传参,这种形式传入的引用不需要初始化,在执行体中也不允许访问其原有值,但可以赋值给输出参数。

需要注意的是:

  • 当方法直接接受数组名作为参数时,实质上这是值传参;但由于数组名本身就是引用,故也起到了引用传参所具有的“影响调用方”的效果,需要注意避免混淆。数组作参数按值传参的形参语法为 TYPE[] PARAM,因为这是值传参,故实参直接传入数组名,不需要加 ref,这种情况下被调方能够修改数组中的内容,但 无法让数组名指向其它内存空间
  • 还可以接受数组名的引用作为参数,这是真正的引用传参,传入了一个“引用的引用”,语法为 ref TYPE[] PARAM,因为这是引用传参,故实参也要加 ref,这时 被调方不仅能够修改数组中的内容,还可以让数组名指向其它内存空间
  • 参数可以有默认值,语法 TYPE PARAM = DEFAULT,与 C++ 一样,所有有默认值的参数都需要位于没有默认值的参数之后。

值传参的例子:

using System;

namespace PassByValue
{
    class SquarePrinter
    {
        public static void Print(uint width, uint height)
        {
            while (height != 0)
            {
                for (int i = 0; i < width; ++i)
                {
                    Console.Write("*");
                }
                Console.WriteLine();
                --height;
            }
        }
    }
    
    class Program
    {
        public static void Main()
        {
            SquarePrinter.Print(16, 8);
            SquarePrinter.Print(8, 4);
            SquarePrinter.Print(4, 2);
        }
    }
}

控制台输出:

****************
****************
****************
****************
****************
****************
****************
****************
********
********
********
********
****
****

引用传参的例子:

using System;

namespace PassByRef
{
    class ArrayToy
    {
        public static void Modify(int[] array, uint pos, int data)
        {
            array[pos] = data;
        }

        public static void Swap(ref int[] l, ref int[] r)
        {
            int[] temp = l;
            l = r;
            r = temp;
        }
    }

    class Program
    {
        static void Main()
        {
            int[] first = {1, 2, 3}, second = {4, 5, 6};
            ArrayToy.Modify(first, 1, 0);
            ArrayToy.Swap(ref first, ref second);

            foreach (int i in first)
            {
                Console.Write(i + " ");
            }
            Console.WriteLine();
            foreach (int i in second)
            {
                Console.Write(i + " ");
            }
        }
    }
}

控制台输出:

4 5 6
1 0 3

输出传参的例子:

using System;

namespace OutputParams
{
    class Program
    {
        static DateTime GetFullDate(out int year, out int month, out int day)
        {
            var now = DateTime.Now;
            year = now.Year;
            month = now.Month;
            day = now.Day;
            return now;
        }

        static void Main()
        {
            var time = GetFullDate(out int y, out int m, out int d);
            Console.WriteLine("Today is {0}-{1}-{2}, {3}", y, m, d, time.DayOfWeek);
        }
    }
}

控制台输出:

Today is 2021-2-19, Friday

这里用到了 Console.WriteLine 的格式化输出,后面会介绍。

可变参数

为实现可变参数个数,可以用前面介绍的参数默认值,也可以用数组传递参数。之前认识过了 Main 方法的形参 string[] args,这就是用数组传递可变参数的例子。

写一个例子来演示这个参数如何使用:

using System;

namespace AdvancedHello
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                Console.WriteLine("Hello, " + args[0] + "!");
            }
            else
            {
                Console.Write("What's your name? ");
                string name = Console.ReadLine();
                Console.WriteLine("Hello, " + name + "!");
            }

            Console.ReadKey();
        }
    }
}

用户通过命令行运行程序时,在命令之后可附带一系列用空格隔开的运行参数,如我们日常使用的 cd 命令,cd 是命令名(对于一个可执行文件),而空格后的路径就是传给它的运行参数。

Main 方法是程序的入口点,它本身的参数由程序之外传入,即用户传入的运行参数。C# 将用户传入的所有运行参按顺序放在 args 数组中,若没有任何运行参数,则 args 元素数为 0(与 C++ 不同,C++ 中运行参数数组一定至少有 1 个元素,该 0 号元素是程序的运行目录)。

上面的程序中我们判断传入的参数数组的元素数是否大于 0 来确定用户是否传入了参数,这种技巧在编写其他方法的可变形参表时也适用。

在 cmd 中 cd 到项目 exe 的构建目录中,并输入 exe 文件名称,加一个空格,输入一些字符串作为运行参数,执行即可看到效果:

...\bin\Debug>AdvancedHello.exe Bug
Hello, Bug!

...\bin\Debug>AdvancedHello.exe
What's your name? Bug
Hello, Bug!

原文地址:https://blog.csdn.net/lfod1997/article/details/113877747

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要介绍了Unity游戏开发中外观模式是什么意思,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家...
这篇文章主要介绍Unity中地面检测方案的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1.普通射线在角色坐标(一般是脚底)...
这篇文章主要介绍了Unity游戏开发中如何消除不想要的黄色警告,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带...
这篇文章主要介绍了Unity中有多少种渲染队列,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解
这篇文章主要介绍Unity中如何实现Texture,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!了解Texture2D 如上图,Texture2D是一张
小编给大家分享一下Unity中DOTS要实现的特点有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让...
这篇文章给大家分享的是有关unity中如何实现UGUI遮罩流光特效的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。下面是核心shader:Sh...
这篇文章主要为大家展示了“Unity中如何实现3D坐标转换UGUI坐标”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下...
这篇文章主要介绍了Unity游戏开发中设计模式的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家...
这篇文章主要介绍了Unity中如何实现仿真丝袜渲染,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了...
这篇文章给大家分享的是有关Unity插件OVRLipSync有什么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。项目需要接入对话口型动...
这篇文章主要介绍了Unity性能优化之DrawCall的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家...
这篇文章给大家分享的是有关Unity给力插件之Final IK怎么用的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。这插件有什么用:一般游...
这篇文章给大家分享的是有关Unity中如何内嵌网页插件UniWebView的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、常见Unity中内...
小编给大家分享一下Unity如何做流体物理的几个轮子,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让...
小编给大家分享一下Unity中Lod和Occlusion Culling的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收...
这篇文章将为大家详细讲解有关Unity中LineRenderer与TrailRenderer有什么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获...
这篇文章主要介绍了Unity中coroutine问题的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起...
这篇文章将为大家详细讲解有关unity中spine怎么用,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。骨骼动画首先我们来看到...
这篇文章主要为大家展示了“Unity Shader后处理中如何实现简单均值模糊”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学...