C#從零開始_自學C#、Visual Studio實境秀 42/ Getting Started with C# Lesson 13~15 of...
{
完善詞牌斷句標韻程式碼{
If 詞牌rst.RecordCount > 1 Then 'Stop
' With p.Previous.Range.Characters.last
' .InsertBefore " "
' With .Previous
' .Font.Size = 12
' .Bold = True
' .Text = "(共" & 詞牌rst.RecordCount & "式)"
' End With
' End With
p.Previous.Range.Characters.last.InsertBefore " " '上面不行此下行,可見 每呼一次 p 即又一個 new p,如 C#裡的 string 或 instance 執行個體 一樣 。這個動作其實是建構了另一個 p 物件執行個體,而不是改了p
With p.Previous.Range.Characters.last.Previous '既然是重新建構一個 p 物件,那麼若不參照此新物件,此新物件便無用了。再 call 一次 p,即取得這個新的 p,而原p 即如舊的 string 被回收一樣
.Font.Size = 12
.Bold = True
.Text = "(共 " & 詞牌rst.RecordCount & "式)" 'p.Parent.Range(p.Previous.Range.Characters.last.End- len("(共" & 詞牌rst.RecordCount & " 種調式:))-1,p.Previous.Range.Characters.last.previous.end).Font.Bold = True
End With
End If
11:00 可見 Word 裡物件取用模式類似 C#中 string 的運作方式。觀念真重要!
所以原來 paragraph 變數被「改寫」,其實是「另建」了一個新的 paragraph 參照的執行個體(物件).所以應當改口,不能說「被『改寫』」了。其實原物根本沒動,動的是創新了一個。
可是, range 的參考(參照),卻是隨著設定而蠻動的。或許是因為用了 「=」 assign (設定)這個 operator 的緣故
1:33:00 1:36:00 前式可改寫成:
Dim CiPaiParagraph As Paragraph
Set CiPaiParagraph = p '可見 Paragraph和Range不同,Range變數設定了就會跟著原Range跑,可見是reference type,而Paragraph 則不會,是(Value Type) instantiated object 執行個體
CiPaiParagraph.Range.Characters.last.InsertBefore " " '上面不行此下行,可見 每呼一次 p 即又一個 new p,如 C#裡的 string 或 instance 執行個體 一樣 。這個動作其實是建構了另一個 p 物件執行個體,而不是改了p
With CiPaiParagraph.Range.Characters.last.Previous '既然是重新建構一個 p 物件,那麼若不參照此新物件,此新物件便無用了。再 call 一次 p,即取得這個新的 p,而原p 即如舊的 string 被回收一樣
.Font.Size = 12
.Bold = True
.Text = "(共 " & DiaoShiCount & "式)" 'p.Parent.Range(p.Previous.Range.Characters.last.End- len("(共" & DiaoShiCount & " 種調式:))-1,p.Previous.Range.Characters.last.previous.end).Font.Bold = True
End With
可見 paragraph 並不同於 range
觀念多重要 弄錯就事倍功半 搞對就事半功倍 差這麼多!
2:27:00 Top 1 、DISTINCT 和二者皆無者,取得記錄效率差不多: 2:39:30
詞牌rst.Open "select TOP 1 詞牌 from [工作表1$] where strcomp(詞牌,""" & 詞牌 & """)=0;", db, adOpenKeyset, adLockReadOnly, 1
2:54:00 其實第一次開啟 recordset 時可能要配置記憶體,所以特別慢,關了之後再開都快了。
}
3:05:00 我 Blogger 原 template
Lesson 13 of 20 Working with Scope and Accessibility Modifiers http://bit.ly/2u0McIx
{
1:16:00 C# is case-sensitive, SQL Access Office VBA .. 就不是
2:25:00 Method Scoping 3:08:20
Any variables declared within a method exist from that point forward in the method, and each time the method is called, new instances of the variables get created.
Cannot use local variable 'width' before it is declared
The name 'length' does not exist in the current context
不會因為宣告了就先讀宣告,而是死板板地一行行地讀、執行
3:18:00 A local or parameter named 'i' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
3:20:40 Class Scoping
Within a method or a block, a variable must be declared before being used.
For class-level scoping, you may reference members declared below the code you're writing.
class-level scoping
在同一 class 其 members 的排序就不重要了。在方法 method 中則否
When an object of this type is created, a variable is created to store the value of Radius. That variable exists and is accessible during the lifetime of that object instance.
關鍵字是「 created 」!
3:29:30 Access Modifiers
3:34:40 DateTime.Today.AddYears(-18); // 沒有減,只有加 Addyears 故用負值
3:39:00 衍生類別繼承了基底類別的建構子,自己就不寫了;只寫引數,引數要寫,而且要一樣。(即方法簽章要一樣)
public Student(string firstName, string lastName, DateTime dateOfBirth)
: base(firstName, lastName, dateOfBirth)
{ }
3:44:30 the internal modifier, but that's more related to the Understanding Namespaces lesson.
3:46:00 屬性也是方法,一種含有 get set 二種方法的組合
Notice that the access modifiers are the first word in the declaration of the classes, methods, and properties. This holds for most cases, however, you'll notice one exception to this in the example:
protected string FirstName { get; private set; }
With properties, it's possible to further restrict the setter method, so that it's less accessible than the getter method.
3:49:00 private 用法的關鍵字就在「in the same class,」!
3:50:00 即使是繼承者也不能存取在 private 宣告下的成員: Because it is private, only the Person class can set this value; the inheriting Student is not even able to modify the value.
3:54:00 internal 也可跨 namespace ,它的用法的關鍵字在「in the same assembly」!
4:08:00 These keep developers without access to your assembly's source code from using the internal code.這些使得那些無權存取您組建源碼的開發人員無法去使用您組建內部的程式碼。
4:20:00 練習 4:37:00{
using System;
using static System.Console;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var jimmy = new Student("Jimmy", "Jones", new DateTime(1990, 3, 15));
var oscar = new Student("Oscar", "Sun", new DateTime(1972, 9, 29));
var vicky = new Student("Vicky", "Sun", new DateTime(1970, 11, 14));
var RuoShui = new Student("RuoShui", "Wang", new DateTime(1969, 3, 10));
Course CourseChinese = new Course("Chinese");
//Console.WriteLine(jimmy.RosterName);
CourseChinese.Add(oscar); CourseChinese.Add(vicky); CourseChinese.Add(RuoShui);//此即註冊或選課的手續
WriteLine("Property:"+CourseChinese.CourseName);
WriteLine("method:"+CourseChinese.CourseNameMethod());
ForegroundColor = ConsoleColor.DarkGreen;
WriteLine("RosterName below:");
ForegroundColor = ConsoleColor.Gray;
CourseChinese.printoutRosterName(CourseChinese);
}
}
public class Person
{
public Person(string firstName, string lastName, DateTime dateOfBirth)
{
this.FirstName = firstName;
this.LastName = lastName;
this.DateOfBirth = dateOfBirth;
}
protected string FirstName { get; private set; }
protected string LastName { get; private set; }
public DateTime DateOfBirth { get; private set; }
public string FullName { get { return $"{this.FirstName} {this.LastName}"; } }
public bool IsAnAdult()
{
var eighteenYearsAgo = DateTime.Today.AddYears(-18);
return this.DateOfBirth < eighteenYearsAgo;
}
}
public class Student : Person
{
public Student(string firstName, string lastName, DateTime dateOfBirth)
: base(firstName, lastName, dateOfBirth)
{ }
public string SchoolName { get; set; }
public string RosterName { get { return $"{this.LastName}, {this.FirstName}"; } }
}
public class Course : List<Student>//主要是學到這個,還可以繼承!
{
public Course(string courseName)
{
CourseName = courseName;
}
internal string CourseName { get; private set; }
public string CourseNameMethod()
{
return $"{CourseName}";
}
public void printoutRosterName(Course crs)
{
foreach(Student s in crs)
{
WriteLine($"{s.FullName}");
}
}
}
}
}
Lesson 14 of 20 Encapsulation and Object-Oriented Design http://bit.ly/2vcSNon
{
4:41:20 Encapsulation 4:43:00 interface 4:50:00 4:55:00 透過接口、仲介(中介)
4:53:00 By breaking functionality out into separate, focused methods and classes, and controlling how these methods access their classes' state through accessibility modifiers, you can achieve good encapsulation in your program's design.
所以都是要分開來集中管理,各司其職的。
4:55:50 Example of Poor Encapsulation
4:56:10 過度使用屬性 A very common example of poor encapsulation is the overuse of properties, especially for collection types.
Usually, these types expose a great deal more functionality than any client code should be able to access, which can result in program bugs.
如我的前面那個練習 CourseChinese.Remove();//這裡可以移除,還得了!
Even if it didn't allow other classes to set the property, the List<Order> type it exposes is itself breaking encapsulation, and allowing collaborators to arbitrarily Remove or even Clear the contents of the collection.
5:26:55 Using Encapsulation To Constrain Operations
5:37:00 Read Only Properties
You can provide access to an object's state while maintaining some encapsulation by using read-only properties.
collection types frequently expose methods for manipulating their contents even if the collection type itself is read only.
5:41:00 只有 get 沒有 set 就是 readonly public string OrderNumber {get; }
5:43:00 初始值應是由建構子的參數來傳遞而設定,而不是直接經由屬性值的設定來設定:Making these changes requires some slight changes to how these classes are used (initial values must be passed in as constructor parameters, not properties).
5:47:00 封裝集合清單 Encapsulating Collections
When it comes to collections, sometimes the best way to protect them is to only expose a copy of the collection's contents.
This can sometimes have performance implications, so you must be careful with such design decisions.
Using this approach, a private collection is used by the object internally, and the property it exposes simply is a copy of this private collection:
private List<Order> _orders = new List<Order>();
public List<Order> Orders
{
get
{
return new List<Order>(_orders);
}
}
5:56:00 The ReadOnlyCollection type can be used as well, though it adds some additional complexity. This helps ensure collaborators have only read only access to the collection:
private List<Order> _orders = new List<Order>();
private ReadOnlyCollection<Order> _ordersView;
public ReadOnlyCollection<Order> Orders
{
get
{
if (_ordersView == null)
{
_ordersView = new ReadOnlyCollection<Order>(_orders);
}
return _ordersView;
}
}
6:11:55 Another approach is to expose the collection as a type with limited capabilities, such as IEnumerable.
private List<Order> _orders = new List<Order>();
public IEnumerable<Order> Orders
{
get
{
return _orders.AsEnumerable(); // in System.Linq namespace
}
}
IEnumerable此法仍有可能被 explicit cast 回 list
6:18:00 The ReadOnlyCollection approach is the safest one to use if you have collections you need to protect.Using this approach, the original code can only force the Orders property into the orders local variable by copying the collection:
orders = customer.Orders.ToList(); // ToList creates a new list and populates it
重點是在 new! copy!
然而即使集合本身為唯讀,其成員(元素)個體未必也是:even if the collection is readonly, its contents often aren't
In all of these cases, in order for the original program code that adds orders to customers to work, the Customer type must expose an AddOrder method:
public void AddOrder(Order order)
{
_orders.Add(order);
}
所以還是若利用建構子只傳引數,再由內部設定,而不直接可由外部設定其屬性值
6:24:30 想要封裝一個集合清單是極度困難的:Encapsulating collections is difficult, because even if the collection is readonly, its contents often aren't.
6:26:00 那不就無解了嗎?Sometimes the only way to achieve this is to use a custom type for this purpose (which may not be worth the effort).
6:30:30 Encapsulating Infrastructure
6:32:10 Infrastructure refers to all of the things outside of your code that your program must interact with, such as the file system, databases, the system clock, email servers, etc.
Working with these systems requires certain implementation-specific code that is generally at a lower level of abstraction than your programming model(assuming you're not writing device drivers or something similar)
6:39:00 資料庫設計 For instance, if the program needs to store a record in a database, it's a more flexible design to encapsulate the database-specific code in a class separate from the business logic that determines something needs to be persisted.
6:42:00 One approach to creating abstractions for infrastructure-based operations that do not expose their implementation details is to define the available operations as interfaces.
6:47:00 Interfaces
C# defines another type called an interface, using the keyword interface. An interface is equivalent to an abstract base class with no implementation, with one key difference: classes can implement multiple interfaces (a class can only inherit from one other class).
宣告、定義 interface :The syntax to declare an interface is similar to that of a class, but property and method definitions cannot have accessibility modifiers or statement blocks (instead, method declarations end with a ;).
public interface IProductRepository
{
List<Product> List();
}
實作 Implementing an interface from a class is done just like inheriting from a class
強迫概括承受 A class that lists an interface in its definition must implement all of that interface's members or a compilation error will occur.
You can use interfaces anywhere you would define, but not instantiate, a type.
只有一個實作了接口的類別的實例,可以被指派為變數或成員的值:Only an instance of a class that implements the interface can be assigned to variable or member defined to be of the interface's type.
7:10:10 只有實現接口的類別它的實例才能被指定給定義為接口類型的變數或成員。
7:18:50 interface 就像個媒婆,不讓你直接看到兩邊的人物。主要是不要直接,而要間接。所以叫 not tightly coupled 剛好就用 couple !
就是中間的牽線人
7:22:00 Interfaces provide a lightweight way to achieve encapsulation by explicitly defining how your program's components will interact. When designing your application, consider defining and specifying interfaces anywhere you want to constrain how much of your objects' structure you want to expose to collaborators.
也就是您有多少的「家珍」想要給「人家」看(到)。這個「人家」,就是 collaborators
你想要讓人家掌握您程式多少部分,就秀出多少部分。所以:At its core, encapsulation is simply "information hiding",
7:24:20 單一責任制:Single Responsibility
When considering how to break up your program's functionality into classes, the Single Responsibility Principle (SRP) can help.
讓 class 分層負責、各司其職
When considering how to break up your program's functionality into classes, the Single Responsibility Principle (SRP) can help.
This principle states that classes and methods should do only one thing, and when your design follows this principle you will tend to have many small, focused classes that are easy to understand and test.
其實我常應用了:When you see a class or method is getting long, consider whether it has too many responsibilities, and whether it makes sense to split it up into multiple, smaller classes and/or methods.
VBA 引數 ByRef 和 ByVal 的差別。ByVal不會被覆寫。預設是 ByRef
7:53:00 Tell, Don't Ask 不要意見調查,要使喚它(對象 object )。把它當奴隸就對了。
都是跟 instance 有關的
8:08:10 New is Glue
9:26:20 可見 collaborators 並不是指人,而是指 instance object you're instantiating collaborators
8:09:40 不要濫用 new :Remember when you're instantiating collaborators that it's often better to request them as method or constructor parameters than to use new directly in your code.
8:31:00 This isn't to say that you should never use new; just be conscious of the fact that when you do, you're gluing your code to a particular implementation.
8:28:00 Use it when you don’t expect you’ll need flexibility in the future. Use it http://bit.ly/2v5PTkq
大概就是 new 會綁死 靈活性變小 可發展性也變少 關鍵字 flexibility 如果用了太多了 new 可能會讓太多的東西黏在一起,動彈不得。所謂 絆手絆腳 綁手綁腳
http://bit.ly/2v5PTkq New is Glue. It binds your code to a particular collaborator. If there is any chance you’ll need to be flexible about which implementation your code will need, it’s worth introducing an interface to keep your code loosely coupled.
keep your code loosely coupled. 關鍵字 就是這個
8:32:00 Explicit Dependencies
8:33:00 interface 的重要性:As you design your program to follow the above principles, it's likely you'll move toward a design with many small, focused classes that interact with one another through interfaces.
設計要靈活有發展性就對了
Explicit Dependencies Principle. This principle states that methods and classes should explicitly require as parameters any collaborating objects they need to function.
大概就是要把需要依賴的條件或前提在宣告區(引數)裡指明出來,才易於維護。才知道它與哪些相關。
9:04:00 多利用參數 Your classes should communicate what they need to perform their actions by requesting any dependencies through their constructor (or, alternately, as method parameters).
Classes that have hidden dependencies (dependencies not explicitly requested as parameters) are dishonest.
They can trick developers into thinking the classes can simply be instantiated and use, but the classes fail when their hidden dependencies are not set up as required.
也可以說這是一種畸形類別 發育不完全的類別。hidden dependencies (dependencies not explicitly requested as parameters)
}
9:44:00 Lesson 15 of 20 Understanding Namespaces http://bit.ly/2tQ5a5D
{In C#, a namespace is a scope in which developers organize their code, 前面學過 namespace 就像 folder directories
9:46:00 Creating Namespaces
When you create a program in C#, the first class you create will be inside of a namespace.
9:48:00 為了程式碼管理,易於尋找。Naming your namespace clearly is important; finding your code later will be much easier with a clear name.
9:49:00 namespace GettingStartedTutorials.CSharp.NamespaceLesson
Notice the . characters are used to create nested namespaces. 巢狀的命名空間
By using this namespace, you are effectively creating three namespaces: GettingStartedTutorials, GettingStartedTutorials.CSharp, and GettingStartedTutorials.CSharp.NamespaceLesson. For now, the first two only contain the next, more specific namespace, and GettingStartedTutorials.CSharp.NamespaceLesson ...
9:55:00 Using Code from Other Namespaces...This is how developers are able to access code from other namespaces.
10:00:00 If you wanted to create an instance of this class inside of your program, you could do it in one of these two ways.
10:01:00 Namespace as a Class Prefix
10:01:40 Declaring Namespace to be in Scope
a using statement. Just type the using keyword followed by the namespace name you want to include in the current scope.
}
}
留言