In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-02 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
Editor to share with you what C# developers need to pay attention to, I believe most people do not know much about it, so share this article for your reference, I hope you will learn a lot after reading this article, let's learn about it!
1. Development process
The Bug and defects of the program often appear in the development process. As long as you make good use of the tools, you can help identify or avoid problems before you release the program.
Standardized code writing
Standardized code writing can make code easier to maintain, especially when code is developed and maintained by multiple developers or teams. Common tools to enforce code normalization are: FxCop, StyleCop, and ReSharper.
Developer's words: please think carefully about these errors before covering them up, and analyze the results. Don't rely on these tools to find errors in your code, because the results may be a far cry from yours.
Code review
Reviewing code and partner programming are common exercises, such as developers deliberately reviewing code written by others. Others are eager to find some bug of code developers, such as coding errors or execution errors.
Reviewing code is a valuable exercise, and because it relies heavily on manual operations, it is difficult to quantify and the accuracy is not satisfactory.
Static analysis
Static analysis doesn't require you to run the code, and you don't have to write test cases to identify code irregularities or flaws. This is a very effective way to find problems, but you need a tool that doesn't have too many false positives. The commonly used static analysis tool in C # is Coverity,CAT,NET,Visual Studio Code Analysis.
Dynamic analysis
Dynamic analysis tools can help you find these bugs when you run your code: security vulnerabilities, performance and concurrency issues. This method is analyzed in the context of execution time, and because of this, its effectiveness is limited by code complexity. Visual Studio provides a large number of dynamic analysis tools, including Concurrency Visualizer, IntelliTrace, and Profiling Tools, etc.
Manager / team leader language: development practice is the best way to practice avoiding common pitfalls. At the same time, pay attention to whether the test tools meet your needs. Try to keep your team's code diagnosis level within control.
test
There are a variety of testing methods: unit testing, system integration testing, performance testing, penetration testing, and so on. In the development phase, the vast majority of test cases are written by developers or testers, so that the program can meet the requirements.
Tests are valid only if you run the correct code. When conducting functional testing, it can also be used to challenge the speed of development and maintenance of developers.
Development best practices
Take more time to choose tools, use the right tools to solve your concerns, and don't add extra work for developers. Let analysis tools and tests run smoothly to find problems, but make sure that the ideas of the code remain clearly in the developer's mind.
Locate the diagnosed problem as quickly as possible (whether through static analysis or testing, such as compilation warnings, standard violations, problem detection, etc.). If the newly emerged problem is ignored because of "unconcern", making it difficult to find later, it will add a lot of work to the code reviewers and pray that they will not be upset.
Please accept these useful suggestions to improve the quality, security, and maintainability of your code, as well as developers'R & D capabilities, coordination capabilities, and predictability of released code.
Target tools that affect consistency, maintainability standardized code writing, static analysis, consistent code review spacing, naming standards, and good readable formats all make it easier for developers to write and maintain code. Accuracy code review, static analysis, dynamic analysis, test code not only need to be grammatically correct, but also need to use the developer's ideas to meet the software requirements. Functional testing can verify that most of the requirements are met: correctness, scalability, robustness, and security. Security standardized code writing, code review, static analysis, dynamic analysis, testing security is a complex issue, any small vulnerability is a potential threat. Developers develop the ability to standardize code writing, static analysis, and test developers can quickly correct errors with the help of tools. Releasing predictability, standardizing code writing, code review, static analysis, dynamic analysis, testing streamlined late-stage activities, and minimizing error location cycles can all make problem discovery earlier. two。 Type of trap
One of the main advantages of C # is its flexible type system, while safe types can help us find errors earlier. By enforcing strict type rules, the compiler can help you maintain good code writing habits. In this respect, the C # language and the .NET Framework provide us with a large number of types to meet the vast majority of needs. Although many developers have a good understanding of general types and are aware of the needs of users, some misunderstandings and misuses still exist.
For more information about the .NTE framework class library, see MSDN library.
Understand and use standard interfaces
Specific interfaces involve commonly used C # features. For example, IDiposable allows the use of common resource management languages, such as the keyword "using". A good understanding of interfaces can help you write smooth C # code and make it easier to maintain.
Avoid using the ICloneable interface-developers never know whether a copied object is a deep copy or a shallow copy. Since there is still no standard to judge whether the operation of the copied object is correct, there is no way to use the interface as a contract meaningfully.
Structural body
Try to avoid writing to structures and treat them as immutable objects to prevent confusion. Memory sharing in scenarios such as multithreading becomes safer. Our approach to the structure is to initialize it when it is created, and if its data needs to be changed, it is recommended to generate a new entity.
Correctly understand which standard types / methods are immutable and return new values (such as strings, dates) instead of mutable objects (such as List.Enumerator).
String
The value of the string may be empty, so you can use some more convenient features at the appropriate time. NullReferenceException errors may occur in value judgment (s.Length==0), while String.IsNullOrEmpty (s) and String.IsNullOrWhitespace (s) make good use of null.
Tag enumeration
Enumerating types and constants can make the code easier to read and show the meaning of values by replacing magic numbers with identifiers.
If you need to generate a large number of enumerated types, then enumerated types with tags are an easier choice:
[Flag] public enum Tag {None = 0x0, Tip = 0x1, Example=0x2}
The following method allows you to use multiple tags in a snippet:
Snippet.Tag = Tag.Tip | Tag.Example
This method is good for data encapsulation, so you don't have to worry about the disclosure of internal collection information when using Tag property getter.
Equality comparisons (equality comparison)
There are two types of equality:
1. Reference equality, that is, both references point to the same object.
two。 Numerical equality, that is, two different reference objects can be considered equal.
In addition, C# also provides a number of equivalence testing methods. The most common methods are as follows:
= = and! = operation
The equivalent method of virtual inheritance by object
Static Object.Equal method
IEquatable interface equivalent method
Static Object.ReferenceEquals method
Sometimes it is difficult to figure out the purpose of using references or value equality. To further understand these and make your work better, please refer to:
MSDN http://msdn.microsoft.com/en-us/library/dd183752.aspx
If you want to cover something, don't forget the tools available on MSDN such as IEquatable, GetHashCode () and so on.
Note the impact of untyped containers on overloading, and consider using the "myArrayList [0] = = myString" method. Array elements are "objects" of compile-time types, so reference equality can be used. Although C# will remind you of these potential errors, unexpected reference equality will not be alerted in some cases during compilation.
3. Class traps encapsulate your data
Classes play an important role in properly managing data. For performance reasons, classes always cache part of the results or make assumptions about the consistency of internal data. Making data permissions public allows you to cache or make assumptions to some extent, and these actions are shown through the potential impact on performance, security, and concurrency. For example, exposing variable member items such as generic sets and arrays allows the user to skip you and modify the structure directly.
Attribute
In addition to being able to control objects through access modifiers, properties also give you precise control over how users interact with your objects. In particular, attributes also let you know the details of reading and writing.
Generic performance helps you build a stable API or provide a data binding resource when overwriting data into getters and setters through storage logic.
Never let an exception occur in the property getter, and avoid modifying the state of the object. This is a requirement for the method, not the getter of the property.
For more information about attributes, see MSDN:
Http://msdn.microsoft.com/en-us/library/ms229006(v=vs.120).aspx
At the same time, we should pay attention to some side effects of getter. Developers are also used to treating member access as a common operation, so they often ignore those side effects when reviewing their code.
Object initialization
You can assign attributes to a newly created object based on the representation it creates. For example, create a new class C object with a given value for the Foo and Bar properties:
New C {Foo=blah, Bar=blam}
You can also generate an anonymous type of entity with a specific attribute name:
Var myAwesomeObject = new {Name= "Foo", Size=10}
The initialization process runs before the function body is constructed, so you need to make sure that this field is initialized before you input it to the constructor. Since the constructor is not yet running, the initialization of the target domain may not involve "this" anyway.
Input parameters for transition specification refinement
To make some special methods easier to control, it's best to use the least number of specific types in the methods you use. For example, use List to iterate in one method:
Public void Foo (List bars) {foreach (var b in bars) {/ / do something with the bar... }}
For other IEnumerable sets, this method performs better, but for a specific parameter List, we need to make the set in the form of a table. Select as few specific types as possible (such as IEnumerable, ICollection, etc.) to maximize the efficiency of your method.
4. Generics
Generics are a powerful tool for defining independent type structures and designing algorithms that force types to be safe.
Replacing untyped sets such as array lists with generic sets like List can improve both security and performance.
When using generics, we can use the keyword "default" to get the default values for the type (these default values cannot be hard-coded into implementation). In particular, the default value for numeric types is o, and the default values for reference types and null types are null.
T = default (T); 5. Type conversion
There are two modes of type conversion. One explicit conversion must be called by the developer, and the other implicit conversion is applied to the compiler based on the environment.
The constant o can be implicitly converted to enumerated data. When you try to call a method that contains numbers, you can convert the data to an enumerated type.
Type conversion description Tree tree = (Tree) obj; this method can be used when the object is of a tree type; if the object is not a tree, an InvalidCast exception may occur. Tree tree = obj as Tree; is a method you can use when predicting whether an object is a tree. If the object is not a tree, the tree is assigned a value of null. You can use the conversion of "as", then find the return of the null value, and then process it. Because it requires conditional return values, remember to use this conversion only when you need it. This extra code may result in some bug and may also reduce the readability of the code.
Conversion usually means one of two things:
The performance of 1.RuntimeType can be much more special than that of the compiler, and the Cast conversion command compiler regards this expression as a more special type. If your idea is not correct, the compiler will output an exception to you. For example: convert an object into a string.
two。 There is a completely different type of value, which is related to the value of Expression. Cast commands the compiler to generate code to associate with the value, or to report an exception without a value. For example: convert double type to int type.
Both types of Cast carry risks. The first kind of Cast asks us a question: "Why do developers know the problem clearly and why can't compilers?" If you are in this situation, you can try to change the program so that the compiler can successfully deduce the correct type. If you think that the runtime type of an object is a more special type than compile time type, you can use "as" or "is".
The second cast also raises the question: "Why not manipulate the target data type in the first step?" If you need results of type int, it makes more sense to use int than double.
For additional information, see:
Http://blogs.msdn.com/b/ericlippert/archive/tags/cast+operator/
Explicit conversion is the right choice in some cases, which can improve code readability and debug capabilities, as well as testing capabilities when appropriate actions are taken.
6. The exception is not a condition
Exceptions should not occur frequently in the program flow. They represent runtime environments that developers don't want to see, and these are probably beyond repair. If you expect a controlled environment, it's much better to take the initiative to check the environment than to wait for problems to arise.
Using the TryParse () method, you can easily convert a formatted string into a number. Whether the parsing is successful or not, it returns a Boolean result, which is much better than simply returning an exception.
Pay attention to using exception handling scope
Pay attention to the use of catch and finally blocks when writing code. Because of these unwanted exceptions, control may enter these blocks. The executed code you expect may be skipped because of an exception. Such as:
Frobber originalFrobber = null;try {originalFrobber = this.GetCurrentFrobber (); this.UseTemporaryFrobber (); this.frobSomeBlobs ();} finally {this.ResetFrobber (originalFrobber);}
If GetCurrentFrobber () reports an exception, the value of originalFrobber is still empty when finally blocks is executed. If GetCurrentFrobber can't be thrown away, why is there a try block inside it?
Handle exceptions wisely
Be careful to handle your target exceptions in a targeted manner, and only deal with the exception parts of the target code. Try not to handle all exceptions, or root exceptions, unless your goal is to record and rehandle them. Some exceptions can put the application in a near-crash state, but this is also much better than being unable to fix it. Some attempts to fix the code may mistakenly make the situation worse.
There are some subtle differences about fatal exceptions, especially focusing on the execution of finally blocks, which can affect the security and debugging of exceptions. For more information, see:
Http://incrediblejourneysintotheknown.blogspot.com/2009/02/fatal-exceptions-and-why-vbnet-has.html
Use a top-of-the-line exception handler to handle exceptions safely and expose some of the problem information about debug. Using catch blocks can safely locate those special situations, thus safely solving these problems, leaving some problems to the top exception handlers.
If you find an exception, please do something to solve it instead of shelving the problem. Shelving will only make the problem more complicated and more difficult to solve.
Including exceptions in a custom exception is particularly useful for code that targets public API. Exceptions are part of the visual interface method, which is also controlled by parameters and return values. However, this method which spreads a lot of exceptions is very troublesome to solve the robustness and maintainability of the code.
Throw (Throw) and continue throwing (ReThrow) exception
If you want to solve caught exceptions at a higher level, then maintain the original exception state, and the stack is a good debug method. However, attention should be paid to maintaining a good balance between debug and security considerations.
Good options include simply continuing to throw exceptions:
Throw
Or re-throw the exception as an internal exception:
Throw a new CustomException
Do not explicitly rethrow caught exceptions like this:
Throw e
This will restore exception handling to its original state and hinder debug.
Some exceptions occur outside the environment in which your code is running. Instead of using caught blocks, you may need to add processors such as ThreadException or UnhandledException to your target. For example, Windows forms exceptions do not occur in the form processing threading environment.
Atomicity (data integrity)
Don't let exceptions affect the integrity of your data model. You need to make sure that your object is in a relatively stable state-so that any operation performed by the class will not break the law. Otherwise, "recovery" will make your code more confusing and prone to further damage.
Consider several ways to change the order of private domains. If an exception occurs during the process of changing the order, your object may not be in an illegal state. Try to get a new value before actually updating the domain so that you can update your domain normally under exception security management.
Assign variables to specific types of values, including Boolean, 32bit, or smaller data types and references, to ensure that they can be atomic. There is no guarantee for some large data (double,long,decimal). Think more about this: use more lock statements when sharing multithreaded variables.
7. Event
Events and delegates together provide a method for classes that alerts the user when something special happens. The value of the delegate event should be called when the event occurs. Events are like fields of delegate type, which are automatically initialized to null when the object is generated.
Events are also like domains with a value of Multicast. That is, one delegate can call other delegates in turn. You can assign a delegate to an event, or you can control the event by doing something like-= to + =.
Pay attention to resource competition
If an event is shared by multiple threads, it is possible for another thread to clear all user information after you check if it is null and before calling it-and throw a NullReferenceException.
The standard solution to such problems is to create a copy of the event for testing and invocation. You still need to note that if the delegate is not called correctly, users who have been removed from other threads can continue to operate. You can also lock the operations sequentially in some way to avoid some problems.
Public event EventHandler SomethingHappened;private void OnSomethingHappened () {/ / The event is null until somebody hooks up to it / / Create our own copy of the event to protect against another thread removing our subscribers EventHandler handler = SomethingHappened; if (handler! = null) handler (this,new EventArgs ();}
For more information about events and competition, see:
Http://blogs.msdn.com/b/ericlippert/archive/2009/04/29/events-and-races.aspx
Don't forget to Unhook the event handler
Using an event handler to generate a reference from the processor's resource object to the receiving object for the event resource can protect the garbage collection at the receiving end.
A proper unhook processor ensures that you don't have to waste time calling a delegate because it no longer works, and it doesn't make memory store useless delegates and non-referenced objects.
8. Attribute
Property provides a way to inject metadata into assemblies, classes, and their information properties. They are often used to provide information to consumers of code-- such as debugger, framework testing, applications-- through reflection. You can also define attributes to your users, or use predefined attributes, as shown in the following table:
Property uses the object destination DebuggerDisplayDebuggerDebugger display format InternalsVisibleToMember access uses a specific class to expose internal members to specify other classes. Based on this approach, the test method can be used to protect members, and the persistence layer can use some special hidden methods. DefaultValueProperties specifies a default value for the property
Be sure to pay more attention to DebuggerStepThrough-otherwise it will make it very difficult to find bug where this method is used, and you will skip a step or push it down and redo it.
9.Debug
Debug is an essential part of the development process. In addition to visualizing the opaque parts of the run-time environment, debugger can also invade the run-time environment and cause the application to realize differently if you don't use debugger.
Make the exception stack visual
To observe the current abnormal state of the frame, you can add the expression "$exception" to the Visual Studio Watch window. This variable contains the current exception state, similar to what you see in catch block, but does not include exceptions that you see in debugger that are not actually present in the code.
Note the side effects of the accessor
If your properties have side effects, consider whether you should use features or debugger settings to prevent debugger from automatically calling getter. For example, your class might have a property like this:
Private int remainingAccesses = 10 * private string meteredData;public string MeteredData {get {if (remainingAccesses-- > 0) return meteredData; return null;}}
The first time you see this object in debugger, remainingAccesses gets an integer variable with a value of 10, and MeteredData is null. However, if you hover the end of remainingAccesses, you will find that its value will become 9. 5. In this way, the property value representation of the debugger changes the state of your object.
10. Performance optimization
Plan early, monitor constantly, and optimize later.
In the design stage, set practical goals. During the development phase, it makes more sense to focus on the correctness of the code than to make fine-tuning. For your goals, you should monitor more during the development process. Only when you don't achieve your desired goals should you take the time to make an adjustment to the program.
Remember to use the right tools to ensure empirical measurement of performance, and to keep testing in an environment where testing can be repeated and the testing process is as consistent as possible with real-world user habits.
When you test performance, be sure to pay attention to what test goals you really care about. When testing a function, does your test include the call to this function or the cost of loop construction?
We have all heard a lot of project myths that can be done much faster than others. Don't blindly believe these. Testing and testing are the real things.
Due to CLR optimization, sometimes seemingly inefficient code may run faster than seemingly efficient code. For example, the CLR optimization loop covers a complete array to avoid checking in the invisible per-element range. Developers often calculate the length of an array before looping through it:
Int [] a_val = int [4000]; int len = axival.Lengthten for (int I = 0; I
< len; i++) a_val[i] = i; 通过将长度存储进一个变量当中,CLR会不去识别这一部分,并且跳过优化。但是有时手动优化会反人类地导致更糟糕的性能表现。 构造字符串 如果你打算将大量的字符串进行连接,可以使用System.Text.StringBuilder来避免生成大量的临时字符串。 对集合使用批量处理 如果你打算生成并填满集合中已知的大量数据,由于再分配的存在,可以用保留空间来解决生成集合的性能与资源问题。你可以用AddRange方法来进一步对性能进行优化,如下在List中处理: Persons.AddRange(listBox.Items);11.资源管理 垃圾收集器(garbage collector)可以自动地清理内存。即使这样,一切被抛弃的资源也需要适当的处理--特别是那些垃圾收集器不能管理的资源。 资源管理问题的常见来源内存碎片如果没有足够大的连续的虚拟地址存储空间,可能会导致分配失败进程限制进程通常都可以读取内存的所有子集,以及系统可用的资源。资源泄露垃圾收集器只管理内存,其他资源需要由应用程序正确管理。不稳定资源那些依赖于垃圾收集器与终结器(finalizers)的资源在很久没用过的时候,不可被立即调用。实际上它们可能永远不可能被调用。 利用try/finally block来确保资源已被合理释放,或是让你的类使用IDisposable,以及更方便更安全的声明方式。 using (StreamReader reader=new StreamReader(file)) { //your code here在产品代码中避免garbage collector 除了用调用GC.Collect()干扰garbage collector之外,也可以考虑适当地释放或是抛弃资源。在进行性能测试时,如果你可以承担这种影响带来的后果,你再去使用garbage collector。 避免编写finalizers 与当前一些流传的谣言不同的是,你的类不需要Finalizers,而这只是因为IDisposable的存在!你可以让IDisposable赋予你的类在任何已拥有的组合实例中调用Dispose的能力,但是finalizers只能在拥有未管理的资源类中使用。 Finalizers主要对交互式Win32位句柄API有很大作用,并且SafeHandle句柄是很容易利用的。 不要总是设想你的finalizers(总是在finalizer线程上运行的)会很好地与其他对象进行交互。那些其他的对象可能在该进程之前就被终止掉了。 12.并发性 处理并发性与多线程编程是件复杂的、困难的事情。在将并发性添加进你的程序之前,请确保你已经明确了解你的做的是什么--因为这里面有太多门道了! 多线程软件的情况很难进行预测,比如很容易产生如竞争条件与死锁的问题,而这些问题并不是仅仅影响单线程应用。基于这些风险,你应该将多线程视为最后一种手段。如果不得不使用多线程,尽量缩减多线程同时使用内存的需求。如果必须使线程同步,请尽可能地使用最高等级的同步机制。在最高等级的前提下,包括了这些机制: Async-await/Task Parallel Library/Lazy Lock/monitor/AutoResetEvent Interlocked/Semaphore 可变域与显式barrier 以上的这些很难解释清楚C#/.NET的复杂之处。如果你想开发一个正常的并发应用,可以去参阅O'Reilly的《Concurrency in C# Cookboo》。 使用Volatile 将一个域标记为"volatile"是一种高级特性,而这种设置也经常被专家所误解。C#的编译器会保证目标域可以被获取与释放语义,但是被lock的域就不适用于这种情况。如果你不知道获取什么,不知道释放什么语义,以及它们是怎样影响CPU层次的优化,那么久避免使用volatile域。取而代之的可以用更高层次的工具,比如Task Parallel Library或是CancellationToken。 线程安全与内置方法 标准库类型常提供使对象线程安全更容易的方法。例如Dictionary.TryGetValue()。使用此类方法一般可以使你的代码变得更加清爽,并且你也不必担心像TOCTOU(time-of-check-time-of-use竞争危害的一种)这样的数据竞争。 不要锁住"this"、字符串,或是其他普通public的对象 当使用在多线程环境下的一些类时,多注意lock的使用。锁住字符串常量,或是其他公共对象,会阻止你锁状态下的封装,还可能会导致死锁。你需要阻止其他代码锁定在同一使用的对象上,当然你最好的选择是使用private对象成员项。 13.避免常见的错误Null 滥用null是一种常见的导致程序错误的来源,这种非正常操作可能会使程序崩溃或是其他的异常。如果你试图获取一个null的引用,就好像它是某对象的有效引用值(例如通过获取一个属性或是方法),那么在运行时就会抛出一个NullReferenceException。 静态与动态分析工具可以在你发布代码之前为你检查出潜在的NullReferenceException。在C#当中,引用型为null通常是由于变量没有引用到某个对象而造成的。对于值可为空的类型与引用型来说,是可以使用null的。例如:Nullable,空委托,已注销的事件,"as"转化失败的,以及一些其他的情况。 每个null引用异常都是一个bug。相比于找到NullReferenceException这个问题来说,不如尝试在你使用该对象之前去为null进行测试。这样一来可以使代码更易于最小化的try/catch block读取。 当从数据库表中读取数据时,注意缺失值可以表示为DBNull 对象,而不是作为空引用。不要期望它们表现得像潜在的空引用一样。 用二进制的数字表示十进制的值 Float与double都可以表示十进制实数,但不能表示二进制实数,并且在存储十进制值的时候可以在必要时用二进制的近似值存储。从十进制的角度来看,这些二进制的近似值通常都有不同的精度与取舍,有时在算数操作当中会导致一些不期望的结果。由于浮点型运算通常在硬件当中执行,因此硬件条件的不可预测会使这些差异更加复杂。 在十进制精度很重要的时候,就要使用十进制了--比如经济方面的计算。 调整结构 有一种常见的错误就是忘记了结构是值类型,意即其复制与通过值传递。例如你可能见过这样的代码: struct P { public int x; public int y; }void M(){ P p = whatever; … p.x = something; … N(p); 忽然某一天,代码维护人员决定将代码重构成这样: void M(){ P p = whatever; Helper(p); N(p);}void Helper(P p){ … p.x = something; 现在当N(p)在M()中被调用,p就有了一个错误的值。调用Helper(p)传递p的副本,并不是引用p,于是在Helper()中的突变便丢失掉了。如果被正常调用,那么Helper应该传递的是调整过的p的副本。 非预期计算 C#编译器可以保护在运算过程中的常量溢出,但不一定是计算值。使用"checked"与"unchecked"两个关键词来标记你想对变量进行什么操作。 不保存返回值 与结构体不同的是,类是引用类型,并且可以适当地修改引用对象。然而并不是所有的对象方法都可以实际修改引用对象,有一些返回的是一个新的对象。当开发者调用后者时,他们需要记住将返回值分配给一个变量,这样才可以使用修改过的对象。在代码审查阶段,这些问题的类型通常会逃过审查而不被发现。像字符串之类的对象,它们是不可变的,因此永远不可能修改这些对象。即便如此,开发者还是很容易忘记这些问题。 例如,看如下 string.Replace()代码: string label = "My name is Aloysius";label.Replace("Aloysius", "secret"); 这两行代码运行之后会打印出"My name is Aloysius" ,这是因为Raeplace方法并没改变该字符串的值。 不要使迭代器与枚举器失效 注意不要在遍历时去修改集合 List myItems = new List{20,25,9,14,50};foreach(int item in myItems){ if (item < 10) { myItems.Remove(item); // iterator is now invalid! // you'll get an exception on the next iteration 如果你运行了这个代码,那么它一在下一项的集合中进行循环,你就会得到一个异常。 正确的处理方法是使用第二个list去保存你想删除的这一项,然后在你想删除的时候再遍历这个list: List myItems = new List{20,25,9,14,50};List toRemove = new List();foreach(int item in myItems){ if (item < 10) { toRemove.Add(item); }}foreach(int item in toRemove){ 如果你用的是C#3.0或更高版本,可以尝试List.RemoveAll: myInts.RemoveAll(item =>(item < 10)); attribute name error
When implementing a property, note that there is a big difference between the name of the property and the name of the member item used in the class. It is easy to use the same name without knowing it, and an endless loop is triggered when the property is obtained.
/ / The following code will trigger infinite recursionprivate string name;public string Name {get {return Name; / / should reference "name" instead.
Be also careful when renaming indirect attributes. For example, data bound in WPF specifies the attribute name as a string. Sometimes inadvertently changing property names may inadvertently cause problems that cannot be solved by the compiler.
The above is all the contents of the article "what do C# developers need to pay attention to". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.