1. 程式人生 > >C#編程筆記一

C#編程筆記一

operator engine 運算符重載 key win enume deb 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

編程筆記

C#編程筆記一