zoukankan      html  css  js  c++  java
  • C# 对象和类型(2) 持续更新

    class PhoneClass 
    {
        public const string DayOfSendingBill = "Monday";
        public int CustomerID;
        public string FirstName;
        public string LastName;
    }

    结构

    struct PhoneStruct
    {
        public const string DayOfSendingBill = "Monday";
        public int CustomerID;
        public string FirstName;
        public string LastName;
    }

    类是存储在堆(heap)上的引用类型,而结构是存储在栈(stack)上的值。较小的数据类型是使用结构,可提供性能。

    类和结构,都需要使用 new 来声明实例。

    PhoneClass phone = new PhoneClass()
    PhoneStruct phone = new PhoneStruct()

    类函数成员

    • 方法是与某个类相关的函数,与数据成员一样,函数成员默认为实例成员,实用static修饰符可以把方法定义为静态方法。
    • 属性是可以从客户端访问的函数组,其访问方式与访问类的公共字段类似。
    • 构造函数是实例化对象时自动调用的特殊函数。它必须与类同名,且不能有返回类型。
    • 终结器(析构函数) 名称与类名相同 前面有个 "~" 符号。
    • C#允许已有的运算符应用于自己的类,进行运算符重载。
    • 索引器允许对象以数组或集合的方式进行索引。

    函数传递参数

    对于复杂的数据类型,按引用传递效率更高,因为按值传递时,必须复制大量数据。

    ref 参数

    迫使值参数通过引用传送给方法,方法对变量所做的改变,都会影响原始对象值。

    static void Main(string[] args)
    {
        int i = 20;
        Console.WriteLine("{0}",i);
        Modify(ref i);
        Console.WriteLine("{0}", i);
        Console.ReadLine();
    }
    
    static void Modify(ref int i)
    {
        i = 100;
    }

    C# 要求传递方法的参数必须进行初始化。

    out参数

    out关键字初始化,传递给该方法的变量可以不初始化,方法返回时,方法内对变量所做的改变,都会保留下来。

    static void Main(string[] args)
    {
        int i;
        Modify(out i);
        Console.WriteLine("{0}", i);
        Console.ReadLine();
    }
    
    static void Modify(out int i)
    {
        i = 100;
    }

    命名参数

    允许是通过参数名,按任意顺序传递。

    static void Main(string[] args)
    {
        Console.WriteLine("{0}", FullName("John", "Doe"));
        Console.WriteLine("{0}", FullName(lastName: "Doe", firstName: "John"));
        Console.ReadLine();
    }
    
    static string FullName(string firstName, string lastName)
    {
        return firstName + " " + lastName;
    }

    可选参数

    可选参数必须提供默认值,且必须是在定义在方法的最后的参数。

    static void Main(string[] args)
    {
        Console.WriteLine("{0}", FullName(firstName: "John"));
        Console.ReadLine();
    }
    
    static string FullName(string firstName, string lastName="Default")
    {
        return firstName + " " + lastName;
    }

    方法重载

    方法名相同,参数的个数 或 类型不同。

    class TestFun
    {
        void DoFun(string result)
        {
            
        }
    
        void DoFun(int result)
        {
    
        }
    }

    方法重载不能使用可选参数,可通过函数重载来实现此目的。

     public void DoFun(string result)
     {
         this.DoFun(result, 0);
     }
    
     public void DoFun(string result,int index)
     {
         Console.WriteLine("DoFun2");
     }
    • 两个方法不能仅在返回类型上有区别。
    • 两个方法不能仅根据参数是声明为ref还是out来区分。

    属性

    private string _someProperty;
    public string SomeProperty
    {
        get { return _someProperty; }
        set { _someProperty = value; }
    }

    自动实现属性

     public string SomeProperty { get; set; }

    属性访问修饰符

    C#允许给属性的 get 和 set 访问器设置不同的访问修饰符。在 get 和 set 访问器中,必须有一个具备属性的访问级别。

    public string SomeProperty { get; private set; }

    通过属性访问字段,需要担心带来性能损失。C#代码会编译为IL,然后在运行时JIT编译为本地可执行代码。JIT编译器可以生成高度优化的代码,并在适当的时候随意地内联代码。任何内联代码完全有ClR决定,不能像C++中像 inline 这样关键字控制方法是否内联。

    构造函数

    构造函数声明一个与类同名的方法,且没有返回类型。

    class TestFun
    {
        private int _number;
        public TestFun(int number)
        {
            this._number = number;
        }
    }
    
    TestFun testFun = new TestFun(12);

    私有化构造函数

    class TestFun
    {
        private int _number;
        private TestFun(int number)
        {
            this._number = number;
        }
    }
    • 类仅用某些静态成员或属性的容器,因此永远不会实例化它。
    • 类仅通过调用某个静态成员函数来实例化

    静态构造函数

    static TestFun()
    {
        
    }

    静态构造函数,是在加载类时,有 .net 运行库调用它,静态构造函数不能带参数,一个类也只能有一个静态构造函数。静态构造函数只能访问静态成员,不能访问类的实例成员。

    无参数的实例构造参数与静态构造参数可以同一类中同时定义。

    class TestFun
    {
        public static readonly string BackColor;
    
        static TestFun()
        {
            DateTime now = DateTime.Now;
            switch (now.DayOfWeek)
            {
                case DayOfWeek.Monday:
                    BackColor = "Green";
                    break;
                default:
                    BackColor = "Red";
                    break;
            }
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("{0}",TestFun.BackColor);
            Console.ReadLine();
        }
    }

    从构造函数中调用其他构造函数

    class Car
    {
        public string description;
        public uint numWheels;
    
        public Car(string description, uint numWheels)
        {
            this.description = description;
            this.numWheels = numWheels;
        }
    
        public Car(string description): this(description, 4)
        {
    
        }
    
        //public Car(string description)
        //{
        //    this.description = description;
        //    this.numWheels = 4;
        //}
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Car car = new Car("Audio");
            Console.WriteLine("{0}    {1}",car.description,car.numWheels);
            Console.ReadLine();
        }
    }

    这是C# 特殊语法,称为构造函数初始化器。注意 初始化器不能有多个调用。

     public Car(string description): this(description, 4)

    只读字段

    只读字段只能在构造函数中给只读字段赋值,只读字段可以是一个实例字段。如果要把只读字段设置为静态,必须显示声明它。

    public static readonly uint StaticCars;
    static Car()
    {
        StaticCars = 12;
    }
    
    public readonly uint SampleCars;
    
    public Car()
    {
        SampleCars = 13;
    }

    静态只读,只能在静态构造函数赋值。实例只读,在实例构造函数赋值。当然也可以在声明时赋值。

    匿名类型

    var 和 new 一起使用创建匿名类型。

    var caption = new {FirstName = "James", LastName = "Leonard"};

    结构

    结构是值类型,定义结构和类完全相同。

    struct Car
    {
        public int nWheel;
        public string description;
    
        public Car(string description,int nWheel)
        {
            this.description = description;
            this.nWheel = nWheel;
        }
    }
    • 结构不支持继承。
    • 对于结构,构造函数是不允许替换的。
    • 使用结构,可以指定字段如何在内存中布局。
    Car car = new Car("Audio",4);
    Console.WriteLine("{0}    {1}",car.description,car.numWheels);
    
    Car car2 = new Car();
    car2.description = "BMW";
    car2.numWheels = 4;
    Console.WriteLine("{0}    {1}", car2.description, car2.numWheels);

    结构分配内存时,速度非常快,因为它们将内联或者保存在栈中。在结构超出了作用作用域,删除也是很快。负面影响,当把结构作为参数传递时,结构的所有内容就被复制,对于类就不会。应使用 ref 参数传递,以避免性能损失。

    结构的构造函数

    构造函数的方式与类定义构造函数方式相同,但不允许定义无参数的构造函数。

    结构不能在绕过构造函数进行赋值,否则会出现编译错误。

    也可以像类一样 提供 Close 或 Dispose 方法。

    弱引用

    只要有代码引用它,就会形成强引用。弱引用创建和使用对象,它在垃圾回收器回收时,就会回收对象并释放内存。

    弱引用由 WeakReference 创建 

    MathTest math = new MathTest();
    WeakReference mathReference = new WeakReference(math);
    if (mathReference.IsAlive)
    {
        math = mathReference.Target as MathTest;
        math.x = 1000;
        math.y = 500;
        Console.WriteLine("{0}", math.Value);
    }

    部分类

    partial 关键字允许把类、结构、方法或接口放在多个文件中。

    用法放在 class、struct、interface前面。

    // MathTest1.cs
    partial class MathTest1
    {
        public void MethodOne()
        {
            
        }
    }
    
    // MathTest2.cs
    partial class MathTest1
    {
        public void MethodTwo()
        {
            
        }
    }

    这样这个类 MathTest1 就拥有了 两个方法。

    静态类

    在 class 前面加上 static,就声明了静态类。静态类里不能拥有实例成员和函数。

     static class Math
     {
         public static int Add(int x, int y)
         {
             return x + y;
         }
     }
    
     class Program
     {
         static void Main(string[] args)
         {
             Math.Add(10, 20);
             Console.ReadLine();
         }
     }

    Object类

    如果定义类时没有指定基类,编译器就会自动假定这个类派生自 Object。

    结构总是派生自 System.ValueType。 System.ValueType 又派生自 System.Object

    System.Object 方法

    • ToString()                         获取对象表示的字符串。如果需要复杂的字符串表示,需要实现 IFormattable 接口。
    • GetHashCode()                  如果对象放在名为映射的数据结构中,就是使用这个方法。使用该方法确定放在什么地方。
    • Equals 和 ReferenceEquals   比较对象相等性
    • Finalize                              类似析构函数,在垃圾回收时,重写Finalize函数,系统会自动调用它,执行。Object 实现的函数,实际什么也没有做。
    • GetType            返回总 System.Type  派生类的一个实例。
    • MemberwiseClone               等到一个浅复制的对象。该方法不是须方法,所以不能重写它。

    ToString实例

    class Money
    {
        public decimal amount;
    
        public override string ToString()
        {
            return "$" + amount.ToString();
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Money money = new Money();
            money.amount = 1000;
            Console.WriteLine("{0}",money);
    
            decimal amount = 200;
            Console.WriteLine("{0}", amount);
    
            Console.ReadLine();
        }
    }

    扩展方法

    假设想在Money中添加一个方法 AddToAmount。但是由于某种原因不能在源文件中修改。此时可以扩展方法。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplicationCShape
    {
        public class Money
        {
            public decimal amount;
    
            public override string ToString()
            {
                return "$" + amount.ToString();
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Money money = new Money();
                money.amount = 1000;
                money.AddToAmount(200);
                Console.WriteLine("{0}",money);
    
                Console.ReadLine();
            }
        }
    }
    
    namespace ConsoleApplicationCShape
    {
        public static class MoneyExtension
        {
            public static void AddToAmount(this Money money, decimal amountToAdd)
            {
                money.amount += amountToAdd;
            }
        }
    }

    如果扩展方法与类方法同名,就不会调用扩展方法。

  • 相关阅读:
    hdu 1455 N个短木棒 拼成长度相等的几根长木棒 (DFS)
    hdu 1181 以b开头m结尾的咒语 (DFS)
    hdu 1258 从n个数中找和为t的组合 (DFS)
    hdu 4707 仓鼠 记录深度 (BFS)
    LightOJ 1140 How Many Zeroes? (数位DP)
    HDU 3709 Balanced Number (数位DP)
    HDU 3652 B-number (数位DP)
    HDU 5900 QSC and Master (区间DP)
    HDU 5901 Count primes (模板题)
    CodeForces 712C Memory and De-Evolution (贪心+暴力)
  • 原文地址:https://www.cnblogs.com/z888/p/5770758.html
Copyright © 2011-2022 走看看