C#编程笔记一

---恢复内容开始---

编程笔记

override与new实现的版本控制

// versioning.cs
// CS0114 expected
public class MyBase
{
   public virtual string Meth1()
   {
      return "MyBase-Meth1";
   }
   public virtual string Meth2()
   {
      return "MyBase-Meth2";
   }
   public virtual string Meth3()
   {
      return "MyBase-Meth3";
   }
}

class MyDerived : MyBase
{
   // Overrides the virtual method Meth1 using the override keyword:
   public override string Meth1()
   {
      return "MyDerived-Meth1";
   }
   // Explicitly hide the virtual method Meth2 using the new
   // keyword:
   public new string Meth2()
   {
      return "MyDerived-Meth2";
   }
   // Because no keyword is specified in the following declaration
   // a warning will be issued to alert the programmer that
   // the method hides the inherited member MyBase.Meth3():
   public string Meth3()
   {
      return "MyDerived-Meth3";
   }

   public static void Main()
   {
      MyDerived mD = new MyDerived();
      MyBase mB = (MyBase) mD;

      System.Console.WriteLine(mB.Meth1());
      System.Console.WriteLine(mB.Meth2());
      System.Console.WriteLine(mB.Meth3());
   }
}

问题:将借口的类型作为返回对象是什么意思。。。

问题在下一个章节的解答中。

就是迭代器的实现,用来和foreach来匹配

另外Unity里的协程用到的也是迭代器的方法。

上个示例代码

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

class testClass : MonoBehaviour
{

    void Start()
    {
        print("?");
        TestEnum _t = new TestEnum(10);
        foreach (string item in _t)
        {
            print(item);
        }

    }
}

class TestEnum : IEnumerable
{
    /// <summary>
    /// 生成n组n位随机数序列
    /// </summary>
   public TestEnum(int num)
    {
        _Id = new string[num];
        for(int i = 0; i < num; i++)
        {
            _Id[i] = UnityEngine.Random.Range(0, 10000f).ToString();
        }
    }

    string[] _Id;
    public IEnumerator GetEnumerator()
    {
       return new TestEnumtor(this);
    }
    class TestEnumtor : IEnumerator
    {
        private TestEnum testEnum;
        private int index = 0;

        public TestEnumtor(TestEnum testEnum)
        {
            this.testEnum = testEnum;
        }

        public object Current
        {
            get
            {
                return testEnum._Id[index];
            }
        }

        public bool MoveNext()
        {
            if (index < testEnum._Id.Length-1)
            {
                index++;
                return true;
            }
            else
            {
                return false;
            }
        }

        public void Reset()
        {
            index = -1;
        }
    }
}

关于结构和类:

起码的一点,结构是值类型,类对象是引用类型。

同样的,传参时结构是按值传递,而类是按引用传递。

结构不能定义默认构造函数

使用 New 运算符创建结构对象时,将创建该结构对象,并且调用适当的构造函数。与类不同的是,结构的实例化可以不使用 New 运算符。如果不使用“新建”(new),那么在初始化所有字段之前,字段将保持未赋值状态,且对象不可用。

对于结构,不像类那样存在继承。一个结构不能从另一个结构或类继承,而且不能作为一个类的基。但是,结构从基类对象继承。结构可实现接口,而且实现方式与类实现接口的方式完全相同。以下是结构实现接口的代码片段:

索引器的用法

就是能用索引器的方式来返回类里的属性,具体在VS里找到indexer这个提示符就可以补全出这个结构来了,不做赘述.

但是需要注意一点,这个方法最好是get和set属性都使用。一旦只使用set属性,还不如直接用方法来实现,不要用索引器

类型转换

隐式转换implicit和显式转换explicit,也比较好理解。语法上也是结合了运算符重载。

定义了同类型的显示转换/隐式转换就不需要定义另外一种了。

另外记住要声明为static。

直接上个例子就行了

   static public implicit operator int(TestEnum te)
    {
        Debug.Log("隐式转换");
        return te.length;
    }
    static public explicit operator int(TestEnum te)
    {
        Debug.Log("显示转换");
        return te.length;
    }

(当然,两个都写在这里是错误的)

隐式转换是非常强力的编程工具,但是也可能带来比较难维护的问题吧感觉。

重载运算符

基本和C++的差不多,但是C#的相对来说灵活一点。比如说,+运算符的第一个参数不一定需要是这个类的对象。不像C++里面那样对于二目运算符里的左操作数对类型有要求。(比如<<这个运算符,重载IO流还需要声明是friend)

上个例

static public  TestEnum operator +(int t1,TestEnum t2)
    {
        return t1+t2.length;
    }

(这个功能太强了)

当然,这么写的前提是,我定义了从int到TestEnum的隐式转换

    static public implicit operator TestEnum(int i)
    {
        return new TestEnum(i);
    }

(所以说隐式转换功力很强劲啊…………)

委托和事件:

之前在《u3d脚本编程》这本书里了解了一些有关知识,再看一遍MSDN上的也就相当于复习。

摘一些MSDN上的TIPs好了,也不能说现在完全理解吧,慢慢理解还是可以的。先码

委托在以下情况下很有用:

  • 调用单个方法。
  • 一个类可能希望有方法规范的多个实现。
  • 希望允许使用静态方法实现规范。
  • 希望类似事件的设计模式。
  • 调用方不需要知道或获得在其上定义方法的对象。
  • 实现的提供程序希望只对少数选择组件“分发”规范实现。
  • 需要方便的组合。

接口在以下情况下很有用:

  • 规范定义将调用的一组相关方法。
  • 类通常只实现规范一次。
  • 接口的调用方希望转换为接口类型或从接口类型转换,以获得其他接口或类。

事件按照.NET的标准来的话,就是最好使用EventHandler,或者它的泛型版本(泛型版本是改变了EventArg的类型,一般是继承了EventArg的类(所以为什么不也做一个Object的泛型安全类型版本呢…………))

下面是一个简单的示例

class testClass : MonoBehaviour
{

    void Start()
    {

        DataElement data1 = new DataElement("alex", 15);
        EventListener eva = new EventListener(data1);

        data1.Name = "tom";
        data1.Age = 13;
    }
}

    class DataElementMessage : EventArgs
    {
        public enum ChangeType
        {
            NAME, AGE, BOTH, NONE
        }
        ChangeType changeType;

        internal ChangeType ChangeType1
        {
            get
            {
                return changeType;
            }

            set
            {
                changeType = value;
            }
        }

        public DataElementMessage(ChangeType changetypes)
        {
            this.ChangeType1 = changetypes;
        }
    }

    class DataElement
    {
        private string name;
        private int age;

        public string Name
        {
            get
            {
                return name;
            }

            set
            {
                name = value;
                Onchange(new DataElementMessage(DataElementMessage.ChangeType.NAME));
            }
        }

        public int Age
        {
            get
            {
                return age;
            }

            set
            {
                age = value;
                Onchange(new DataElementMessage(DataElementMessage.ChangeType.AGE));
            }
        }

        public event EventHandler<DataElementMessage> change;

        void Onchange(DataElementMessage e)
        {
            if (change != null)
            {
                change(this, e);
            }
        }

        public DataElement(string name, int age)
        {
            this.Name = name;
            this.Age = age;
            Onchange(new DataElementMessage(DataElementMessage.ChangeType.BOTH));
        }

    }
    class EventListener
    {

        DataElement _eventsender;

       public EventListener(DataElement _e)
        {
            this._eventsender = _e;
            _e.change += ListChange;
        }

        public void ListChange(object sender, DataElementMessage message)
        {
            DataElement data = sender as DataElement;
            Debug.Log("changeType:" + message.ChangeType1.ToString() + "   Age:" + data.Age + "  Name:" + data.Name);
        }

    }

(当然这个实例没有写Detach,要写也比较容易把,写这个也就是熟悉一下基本框架。注意与MVC的联合思考就好)

显式实现接口:

怎么显式实现借口VS已经在自动补全里告诉你了。这里的关键是使用。

如果一个接口是显式实现的,like this

interface testInterface
{
    float Floating();
}
class FloatInterface : testInterface
{
    float testInterface.Floating()
    {
        return 2f;
    }
}

那么使用的时候,就必须用接口对象来实现,like this

        FloatInterface I = new FloatInterface();
        testInterface i = (testInterface)I;

       Debug.Log( i.Floating());

如果是非显式实现的,那么用FloatInterface的实例对象也可以进行接口调用,反之则不行。

那么这个东西有什么用呢?官方例子里大概意思这么写了一个例子,我也简化随便写了下

interface DoubleInterFace
{
    float Floating();
}
interface TrippleInterFace
{
    float Floating();
}
class FloatInterface : DoubleInterFace, TrippleInterFace
{
    float DoubleInterFace.Floating()
    {
        return 2f;
    }

    float TrippleInterFace.Floating()
    {
        return 3f;
    }
  public float Floating()
    {
        return 1f;
    }
}

class testClass : MonoBehaviour
{

    void Start()
    {
        FloatInterface _1f = new FloatInterface();
        TrippleInterFace _3f = _1f;
        DoubleInterFace _2f = _1f;
        Debug.Log(_1f.Floating());
        Debug.Log(_2f.Floating());
        Debug.Log(_3f.Floating());

    }
}

输出当然是1 2 3

编程笔记

时间: 2024-10-26 00:29:42

C#编程笔记一的相关文章

python核心编程--笔记

python核心编程--笔记 的解释器options: 1.1 –d   提供调试输出 1.2 –O   生成优化的字节码(生成.pyo文件) 1.3 –S   不导入site模块以在启动时查找python路径 1.4 –v   冗余输出(导入语句详细追踪) 1.5 –m mod 将一个模块以脚本形式运行 1.6 –Q opt 除法选项(参阅文档) 1.7 –c cmd 运行以命令行字符串心事提交的python脚本 1.8 file   以给定的文件运行python脚本 2 _在解释器中表示最后

C++windows内核编程笔记day07_day08,可视化建菜单、加速键使用、绘图等

可视化操作创建的菜单,加载到窗口. 方法1:注册时指定菜单 wce.lpszMenuName=MAKEINTRESOURCE(IDR_MENUMAIN);//数字形式的资源ID转换为字符串形式的资源 方法2: //创建窗口时加载菜单资源 HMENU menumain= LoadMenu(g_hinstance,MAKEINTRESOURCE(IDR_MENUMAIN)); menumain 传入 CreateWindowEx();//倒数第三个参数 窗口指定小图标: 1.注册时指定 wce.hI

C++windows内核编程笔记day09_day10,对话框和窗口基本控件等的使用

//设置字体颜色 SetTextColor(hdc,RGB(255,0,0)); //窗口背景 //wce.hbrBackground=(HBRUSH)(COLOR_WINDOW+1); //wce.hbrBackground=CreateSolidBrush(RGB(0,0,255)); //设置字体背景 SetBkColor(hdc,RGB(0,0,200)); //设置字体背景模式 SetBkMode(hdc,TRANSPARENT);//字体背景透明 //创建字体,成功返回字体,失败返回

Azure编程笔记(3):用Fiddler调试Azure的应用程序

 内容提要 Azure的服务是通过RESTfulAPI提供的.虽然Azure针对很多编程语言都提供了SDK,但这些SDK也只是RESTfulAPI的一层封装.在调用SDK或者RESTfulAPI出错时,我们需要使用调试工具来分析并解决问题.Fiddler是一款功能强大的免费工具,我们可以使用Fiddler来调试Azure的应用程序.本文展示如何用Fiddler调试一个常见的访问Storage的问题. 问题描述 在前面的两篇博客中,我们模拟社交网站定义了一个Account类型.本文我们继续以A

linux网络编程笔记——TCP

1.TCP和UDP TCP是长连接像持续的打电话,UDP是短消息更像是发短信.TCP需要消耗相对较多的资源,但是传输质量有保障,UDP本身是不会考虑传输质量的问题. 2.网络传输内容 我习惯的做法是直接通过TCP传送结构体,当然前提是收发两端都在程序里对目标结构体有充分的定义.特别说明的一点是,要小心收发两端处理器的大小端问题!而且传输信息头里必须包含长度信息,而且通用的是大端.但是,这里的长度和结构体,我选择用小端进行传输. 3.TCPserver实现 参考了别人多线程的回调写法,看起来不错.

4.28 UNIX环境高级编程 笔记

int dup(int filedes); int dup2(int filedes,int filedes2); 这两个函数都可以实现复制一个现存的文件描述符,但是dup一定返回当前可用最小文件描述符,dup2可以用filedes2参数指定新描述符数值.如果filedes2已经打开,则先将其关闭.如果filedes等于filedes2,则返回filedes2而不关闭. 这些函数返回的新文件描述符与参数参数filesdes共享同一个文件表项. 图3 执行dup之后的内核数据结构 dup2是原子操

DSP28377S - ADC学习编程笔记

DSP28377S -  ADC学习编程笔记 彭会锋 2016-08-04  20:19:52 1 ADC类型导致的配置区别 F28377S的ADC类型是Type 4类型,我的理解是不同类型的ADC采样方式是不一样的:F28335ADC 采样序列可以配置为顺序采样和同步采样模式,而F28377S采样序列可以配置为round-robin or burst模式,这两种模式下面再讲解. 2 ADC上电配置步骤 首先明确一点,ADC是专用管脚,不需要配置GPIO,所以可以直接配置ADC的寄存器 //Wr

多线程编程笔记

多线程的问题 在多线程应用中,子线程一定会修改某些公共资源(包括全局变量.磁盘文件等),这样很有可能会影响其它子线程.由于不同线程是并行执行的,有可能某个时刻某个线程对公共资源进行了部分修改,此时公共资源是无效的,CPU 切换到另一个线程执行并访问此公共资源,这样将有可能造成巨大灾难. 要解决此问题,就应该使需要相同公共资源的不同线程不能同时执行,所以多线程问题分析的基础是互斥. 线程同步和线程互斥 线程间的关系可以分为无关和相交两种.当多个线程无关的时候,其中某个线程的启动不会依赖于另一个线程

linux网络编程笔记——UDP

目前这部分代码会出现阻塞问题,暂时尚未解决 #include "udp.h" #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <malloc.h> #include <sys/types.h> #include <sys/socket