Valid tive C # Principle 29: The new modifier is used only when the base class is forced to be updated)

Source: Internet
Author: User

Valid tive C # Principle 29: The new modifier is used only when the base class is forced to be updated.

Item 29: use the new modifier only when base class updates mandate it

You can use the new modifier to redefine a non-Virtual Member inherited from the base class. You can do this, but it does not mean you need to do this. Redefinition of non-virtual methods can lead to confusion in the meaning of methods. If two related classes are inherited, many developers may assume thatCodeBlocks do exactly the same thing, and they also think:

Object C = makeobject ();

// Call through myclass reference:
Myclass Cl = C as myclass;
Cl. magicmethod ();

// Call through myotherclass reference:
Mytherclass Cl2 = C as mytherclass;
Cl2.magicmethod ();

Once the new modifier is used, the problem is completely different:

Public class myclass
{
Public void magicmethod ()
{
// Details elided.
}
}

Public class mytherclass: myclass
{
// Redefine magicmethod for this class.
Public new void magicmethod ()
{
// Details elided
}
}

Such operations will confuse many developers. Because when you call the same function on the same object, you must expect them to execute the same code. But actually, when you call functions with the same name using different references, their behavior is different, which is very bad. They are inconsistent. The behavior of a mytherclass object varies depending on the method you reference. This is the consequence of using the new modifier on non-Virtual members. In fact, this only allows you to add a different method to the class namespace (although their function names are the same ).

Non-virtual methods are statically bound. No matter where the code is, or where it is referenced, myclass. magicmethod () always strictly calls the functions defined in the class. Different versions are not found in the derived class at runtime. On the other hand, virtual functions are dynamic. The runtime calls different versions based on different types of objects.

We recommend that you avoid using the new modifier to redefine non-virtual functions. This does not need to be explained too much, just as we recommend that you use virtual methods when defining a base class. The designer of a class library should design virtual functions according to a certain contract. This means that you expect any derived class to modify the implementation of the virtual function. The set of virtual functions is equivalent to defining a set of behaviors, which are re-implemented in the derivation. The default virtual function is designed to derive and modify all virtual behaviors in the class. This does mean that you do not want to consider the differences between all derived classes that may need to modify behavior. On the contrary, you can take the time to consider what kind of methods and attributes are designed to be polymorphism. Of course, this can be done only when they are virtual. Do not consider restricting users. On the contrary, it should be considered that this provides an entry wizard for user-defined behaviors of the type.

There is only one case where the new modifier is used, that is, when the class is integrated into an existing base class, and the base class already uses an existing method name, now we need to use new (Note: Both the base class and the derived class already exist. It is the inheritance relationship that was added later. When we add the inheritance relationship, if the same method name is used in the two classes, you can add a new in the derived class to solve this problem ). Because some code is already based on the method name of the class, or there are otherProgramSet to use this method. For example, you have created the following class in the library and used the basewidget defined in another library:

Public class mywidget: basewidget
{
Public void dowidgetthings ()
{
// Details elided.
}
}

You have completed your widget and you can use it. However, you find that basewidget has released a new version. This is exactly what you desire, so you buy and compile your mywidget class immediately. The result failed because basewidget members have added their own dowidgetthings method:

Public class basewidget
{
Public void dowidgetthings ()
{
// Details elided.
}
}

This is a problem. Your base class hides a method, which is in the namespace of your class. There are two ways to solve this problem. One is to modify the method name in your class:
Public class mywidget: basewidget
{
Public void domywidgetthings ()
{
// Details elided.
}
}

Or use the new modifier:

Public class mywidget: basewidget
{
Public new void dowidgetthings ()
{
// Details elided.
}
}

If you can obtain allSource code, You should choose to modify the method name, because it will be easier for future operations. However, if you have released the mywidget class to people all over the world, this will force all users to complete this many changes. This is the problem that the new modifier is easy to solve. You do not need to modify the dowidgetthings () method to continue using it. No one will call the basewidget. dowidgetthings () method because (for a derived class) they do not exist at all. When updating a base class, you can use the new modifier to solve this problem if it finds that it conflicts with the previously stated members.

Of course, in some cases, your users may want to call the widgets of the base class. dowidgetthings () method, then you return to the original problem: the two methods look the same, but they are actually different. Considering the long-standing ambiguity of the new modifier, sometimes it is difficult to change the method to the best strategy in the short term. Long pain is worse than short pain. Haha)

The new modifier must be used with caution. If it is ambiguous, you create a fuzzy method on the class. This is used only in special cases, that is, when the base class is upgraded, it conflicts with your class. Even in this case, you should use it with caution. Most importantly, do not use it any time.

======================================

Item 29: use the new modifier only when base class updates mandate it
You use the new modifier on a class member to redefine a nonvirtual member inherited from a base class. just because you can do something doesn't mean you shoshould, though. redefining nonvirtual Methods creates ambiguous behavior. most developers wowould look at these two blocks of code and immediately assume that they did exactly the same thing, if the two classes were related by inheritance:

Object C = makeobject ();

// Call through myclass reference:
Myclass Cl = C as myclass;
Cl. magicmethod ();

// Call through myotherclass reference:
Mytherclass Cl2 = C as mytherclass;
Cl2.magicmethod ();

 

When the new modifier is involved, that just isn't the case:

Public class myclass
{
Public void magicmethod ()
{
// Details elided.
}
}

Public class mytherclass: myclass
{
// Redefine magicmethod for this class.
Public new void magicmethod ()
{
// Details elided
}
}

 

This kind of practice leads to much developer confusion. if you call the same function on the same object, you need to CT the same code to execute. the fact that changing the reference, the label, that you use to call the function changes the behavior feels very wrong. it's inconsistent. A mytherclass object behaves differently in response to how you refer to it. the new modifier does not make a nonvirtual method into a virtual method after the fact. instead, it lets you add a different method in your class's naming scope.

nonvirtual methods are statically bound. any source code anywhere that references myclass. magicmethod () CILS exactly that function. nothing in the runtime looks for a different version defined in any Derived classes. virtual functions, on the other hand, are dynamically bound. the runtime invokes the proper function based on the runtime type of the object.

the recommendation to avoid using the new modifier to redefine nonvirtual functions shocould not be interpreted as a recommendation to make everything virtual when you define base classes. A library designer makes a contract when making a function virtual. you indicate that any derived class is expected to change the implementation of virtual functions. the set of virtual functions defines all behaviors that derived classes are expected to change. the "virtual by default" design says that derived classes can modify all the behavior of your class. it really says that you didn't think through all the ramifications of which behaviors Derived classes might want to modify. instead, spend the time to think through what methods and properties are intended as polymorphic. make thoseand only thosevirtual. don't think of it as restricting the users of your class. instead, think of it as providing guidance for the entry points you provided for customizing the behavior of your types.

There is one time, and one time only, when you want to use the new modifier. you add new to infully ate a new version of a base class that contains a method name that you already use. you 've already got code that depends on the name of the method in your class. you might already have other assemblies in the field that use this method. you 've created the following class in your library, using basewidget that is defined in another library:

Public class mywidget: basewidget
{
Public void dowidgetthings ()
{
// Details elided.
}
}

 

You finish your widget, and customers are using it. then you find that the basewidget company has released a new version. eagerly awaiting new features, you immediately purchase it and try to build your mywidget class. it fails because the basewidget folks have added their own dowidgetthings method:

Public class basewidget
{
Public void dowidgetthings ()
{
// Details elided.
}
}

 

This is a problem. Your base class snuck a method underneath your class's naming scope. There are two ways to fix this. You cocould change that name of your dowidgetthings method:

Public class mywidget: basewidget
{
Public void domywidgetthings ()
{
// Details elided.
}
}

 

Or, you cocould use the new modifier:

Public class mywidget: basewidget
{
Public new void dowidgetthings ()
{
// Details elided.
}
}

 

If you have access to the source for all clients of the mywidget class, you should change the method name because it's easier in the long run. however, if you have released your mywidget class to the world, that wocould force all your users to make numerous changes. that's where the new modifier comes in handy. your clients will continue to use your dowidgetthings () method without changing. none of them wocould be calling basewidget. dowidgetthings () because it did not exist. the new modifier handles the case in which an upgrade to a base class now collides with a member that you previously declared in your class.

Of course, over time, your users might begin wanting to use the base widget. dowidgetthings () method. then you are back to the original problem: two methods that look the same but are different. think through all the long-term ramifications of the new modifier. sometimes, the short-term inconvenience of changing your method is still better.

The new modifier must be used with caution. if you apply it indiscriminately, you create ambiguous method callin your objects. it's for the special case in which upgrades in your base class cause collisions in your class. even in that situation, think carefully before using it. most importantly, don't use it in any other situations.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.