青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

C++ Programmer's Cookbook

{C++ 基礎} {C++ 高級} {C#界面,C++核心算法} {設計模式} {C#基礎}

c# 函數中傳入參數的類型(Parameter Passing in C# - Preamble)(very good )

Preamble: what is a reference type?

In .NET (and therefore C#) there are two main sorts of type: reference types and value types. They act differently, and a lot of confusion about parameter passing is really down to people not properly understanding the difference between them. Here's a quick explanation:

A reference type is a type which has as its value a reference to the appropriate data rather than the data itself. For instance, consider the following code:

StringBuilder sb = new StringBuilder();

(I have used StringBuilder as a random example of a reference type - there's nothing special about it.) Here, we declare a variable sb, create a new StringBuilder object, and assign to sb a reference to the object. The value of sb is not the object itself, it's the reference. Assignment involving reference types is simple - the value which is assigned is the value of the expression/variable - i.e. the reference. This is demonstrated further in this example:

StringBuilder first = new StringBuilder();
StringBuilder second = first;

Here we declare a variable first, create a new StringBuilder object, and assign to first a reference to the object. We then assign to second the value of first. This means that they both refer to the same object. They are still, however, independent variables themselves. Changing the value of first will not change the value of second - although while their values are still references to the same object, any changes made to the object through the first variable will be visible through the second variable. Here's a demonstration of that:

StringBuilder first = new StringBuilder();
StringBuilder second = first;
first.Append ("hello");
first = null;
Console.WriteLine (second);

Output:

Here, we declare a variable first, create a new StringBuilder object, and assign to first a reference to the object. We then assign to second the value of first. We then call the Append method on this object via the reference held in the first variable. After this, we set the first variable to null (a value which doesn't refer to any object). Finally, we print out the results of calling the ToString method on the StringBuilder object via the reference held in the second variable. hello is displayed, demonstrating that even though the value of first has changed, the data within the object it used to refer to hasn't - and second still refers to that object.

Class types, interface types, delegate types and array types are all reference types.

Further preamble: what is a value type?

While reference types have a layer of indirection between the variable and the real data, value types don't. Variables of a value type directly contain the data. Assignment of a value type involves the actual data being copied. Take a simple struct, for example:

public struct IntHolder
{
? ? public int i;
}

Wherever there is a variable of type IntHolder, the value of that variable contains all the data - in this case, the single integer value. An assignment copies the value, as demonstrated here:

IntHolder first = new IntHolder();
first.i=5;
IntHolder second = first;
first.i=6;
Console.WriteLine (second.i);

Output:

Here, second.i has the value 5, because that's the value first.i has when the assignment second=first occurs - the values in second are independent of the values in first apart from when the assignment takes place.

Simple types (such as float, int, char), enum types and struct types are all value types.

Note that many types (such as string appear in some ways to be value types, but in fact are reference types. These are known as immutable types. This means that once an instance has been constructed, it can't be changed. This allows a reference type to act similarly to a value type in some ways - in particular, if you hold a reference to an immutable object, you can feel comfortable in returning it from a method or passing it to another method, safe in the knowledge that it won't be changed behind your back. This is why, for instance, the string.Replace doesn't change the string it is called on, but returns a new instance with the new string data in - if the original string were changed, any other variables holding a reference to the string would see the change, which is very rarely what is desired.

Constrast this with a mutable (changeable) type such as ArrayList - if a method returns the ArrayList reference stored in an instance variable, the calling code could then add items to the list without the instance having any say about it, which is usually a problem. Having said that immutable reference types act like value types, they are not value types, and shouldn't be thought of as actually being value types.

For more information about value types, reference types, and where the data for each is stored in memory, please see my other article about the subject.

Value Parameters

There are four different kinds of parameters in C#: value parameters (the default), reference parameters (which use the ref modifier), output parameters (which use the out modifier), and parameter arrays (which use the params modifier). You can use any of them with both value and reference types. When you hear the words "reference" or "value" used (or use them yourself) you should be very clear in your own mind whether you mean that a parameter is a reference or value parameter, or whether you mean that the type involved is a reference or value type. If you can keep the two ideas separated, they're very simple.

By default, parameters are value parameters. This means that a new storage location is created for the variable in the function member declaration, and it starts off with the value that you specify in the function member invocation. If you change that value, that doesn't alter any variables involved in the invocation. For instance, if we have:

void Foo (StringBuilder x)
{
? ? x = null;
}
...
StringBuilder y = new StringBuilder();
y.Append ("hello");
Foo (y);
Console.WriteLine (y==null);

Output:

The value of y isn't changed just because x is set to null. Remember though that the value of a reference type variable is the reference - if two reference type variables refer to the same object, then changes to the data in that object will be seen via both variables. For example:

void Foo (StringBuilder x)
{
? ? x.Append (" world");
}
...
StringBuilder y = new StringBuilder();
y.Append ("hello");
Foo (y);
Console.WriteLine (y);

Output:

After calling Foo, the StringBuilder object that y refers to contains "hello world", as in Foo the data " world" was appended to that object via the reference held in x.

Now consider what happens when value types are passed by value. As I said before, the value of a value type variable is the data itself. Using the previous definition of the struct IntHolder, let's write some code similar to the above:

void Foo (IntHolder x)
{
? ? x.i=10;
}
...
IntHolder y = new IntHolder();
y.i=5;
Foo (y);
Console.WriteLine (y.i);

Output:

When Foo is called, x starts off as a struct with value i=5. Its i value is then changed to 10. Foo knows nothing about the variable y, and after the method completes, the value in y will be exactly the same as it was before (i.e. 5).

As we did earlier, check that you understand what would happen if IntHolder was declared as a class instead of a struct. You should understand why y.i would be 10 after calling Foo in that case.

Reference Parameters

Reference parameters don't pass the values of the variables used in the function member invocation - they use the variables themselves. Rather than creating a new storage location for the variable in the function member declaration, the same storage location is used, so the value of the variable in the function member and the value of the reference parameter will always be the same. Reference parameters need the ref modifier as part of both the declaration and the invocation - that means it's always clear when you're passing something by reference. Let's look at our previous examples, just changing the parameter to be a reference parameter:

void Foo (ref StringBuilder x)
{
? ? x = null;
}
...
StringBuilder y = new StringBuilder();
y.Append ("hello");
Foo (ref y);
Console.WriteLine (y==null);

Output:

Here, because a reference to y is passed rather than its value, changes to the value of parameter x are immediately reflected in y. In the above example, y ends up being null. Compare this with the result of the same code without the ref modifiers.

Now consider the struct code we had earlier, but using reference parameters:

void Foo (ref IntHolder x)
{
? ? x.i=10;
}
...
IntHolder y = new IntHolder();
y.i=5;
Foo (ref y);
Console.WriteLine (y.i);

Output:

The two variables are sharing a storage location, so changes to x are also visible through y, so y.i has the value 10 at the end of this code.

Sidenote: what is the difference between passing a value object by reference and a reference object by value?

You may have noticed that the last example, passing a struct by reference, had the same effect in this code as passing a class by value. This doesn't mean that they're the same thing, however. Consider the following code:

void Foo (??? IntHolder x)
{
? ? x = new IntHolder();
}
...
IntHolder y = new IntHolder();
y.i=5;
Foo (??? y);

In the case where IntHolder is a struct (i.e. a value type) and the parameter is a reference parameter (i.e. replace ??? with ref above), y ends up being a new IntHolder value - i.e. y.i is 0. In the case where IntHolder is a class (i.e. a reference type) and the parameter is a value parameter (i.e. remove ??? above), the value of y isn't changed - it's a reference to the same object it was before the function member call. This difference is absolutely crucial to understanding parameter passing in C#, and is why I believe it is highly confusing to say that objects are passed by reference by default instead of the correct statement that object references are passed by value by default.

Output Parameters & Parameter Arrays

Output parameters

Like reference parameters, output parameters don't create a new storage location, but use the storage location of the variable specified on the invocation. Output parameters need the out modifier as part of both the declaration and the invocation - that means it's always clear when you're passing something as an output parameter.

Output parameters are very similar to reference parameters. The only differences are:

  • The variable specified on the invocation doesn't need to have been assigned a value before it is passed to the function member. If the function member completes normally, the variable is considered to be assigned afterwards (so you can then "read" it).
  • The parameter is considered initially unassigned (in other words, you must assign it a value before you can "read" it in the function member).
  • The parameter must be assigned a value before the function member completes normally.

Here is some example code showing this, with an int parameter (int is a value type, but if you understood reference parameters properly, you should be able to see what the behaviour for reference types is):

void Foo (out int x)
{
? ? // Can't read x here - it's considered unassigned
? ? // Assignment - this must happen before the method can complete normally
? ? x = 10;
? ? // The value of x can now be read:
? ? int a = x;
}
...
// Declare a variable but don't assign a value to it
int y;

// Pass it in as an output parameter, even though its value is unassigned
Foo (out y);
// It's now assigned a value, so we can write it out:
Console.WriteLine (y);

Output:

Parameter arrays

Parameter arrays allow a variable number of arguments to be passed into a function member. The definition of the parameter has to include the params modifier, but the use of the parameter has no such keyword. A parameter array has to come at the end of the list of parameters, and must be a single-dimensional array. When using the function member, any number of parameters (including none) may appear in the invocation, so long as the parameters are each compatible with the type of the parameter array. Alternatively, a single array may be passed, in which case the parameter acts just as a normal value parameter. For example:

void ShowNumbers (params int[] numbers)
{
? ? foreach (int x in numbers)
? ? {
? ? ? ? Console.Write (x+" ");
? ? }
? ? Console.WriteLine();
}
...

int[] x = {1, 2, 3};
ShowNumbers (x);
ShowNumbers (4, 5);

Output:

In the first invocation, the variable x is passed by value, as it's just an array. In the second invocation, a new array of ints is created containing the two values specified, and a reference to this array is passed.

Mini-glossary

Some informal definitions and summaries of terms:

Function member
A function member is a method, property, event, indexer, user-defined operator, instance constructor, static constructor, or destructor.
Output parameter
A parameter very similar to a reference parameter, but with different definite assignment rules.
Reference parameter (pass-by-reference semantics)
A parameter which shares the storage location of the variable used in the function member invocation. As they share the same storage location, they always have the same value (so changing the parameter value changes the invocation variable value).
Reference type
Type where the value of a variable/expression of that type is a reference to an object rather than the object itself.
Storage location
A portion of memory holding the value of a variable.
Value parameter (the default semantics, which are pass-by-value)
A value parameter that has its own storage location, and thus its own value. The initial value is the value of the expression used in the function member invocation.
Value type
Type where the value of a variable/expression of that type is the object data itself.
Variable
Name associated with a storage location and type. (Usually a single variable is associated with a storage location. The exceptions are for reference and output parameters.)

posted on 2006-04-07 19:45 夢在天涯 閱讀(2110) 評論(0)  編輯 收藏 引用 所屬分類: C#/.NET

公告

EMail:itech001#126.com

導航

統計

  • 隨筆 - 461
  • 文章 - 4
  • 評論 - 746
  • 引用 - 0

常用鏈接

隨筆分類

隨筆檔案

收藏夾

Blogs

c#(csharp)

C++(cpp)

Enlish

Forums(bbs)

My self

Often go

Useful Webs

Xml/Uml/html

搜索

  •  

積分與排名

  • 積分 - 1812203
  • 排名 - 5

最新評論

閱讀排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
      <noscript id="pjuwb"></noscript>
            <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
              <dd id="pjuwb"></dd>
              <abbr id="pjuwb"></abbr>
              国产精品视频一区二区高潮| 久久久久成人精品免费播放动漫| 亚洲在线国产日韩欧美| 亚洲激情偷拍| 日韩五码在线| 亚洲免费视频在线观看| 性欧美激情精品| 久久米奇亚洲| 亚洲激情啪啪| a4yy欧美一区二区三区| 亚洲欧美变态国产另类| 久久激情视频久久| 欧美精品激情blacked18| 国产精品视频免费在线观看| 国产亚洲成av人在线观看导航| 黄色亚洲大片免费在线观看| 亚洲精品乱码久久久久久黑人| 亚洲尤物视频网| 日韩视频在线免费观看| 蜜桃精品一区二区三区| 免费毛片一区二区三区久久久| 亚洲第一色在线| 亚洲一二区在线| 久久综合一区二区三区| 欧美日韩性生活视频| 国产丝袜一区二区| 日韩一级不卡| 鲁大师成人一区二区三区| 日韩视频在线观看免费| 久久久久久久波多野高潮日日 | 国产精品视频网| 亚洲第一网站| 欧美自拍偷拍午夜视频| 亚洲日本中文字幕免费在线不卡| 亚洲欧美一级二级三级| 欧美日韩另类国产亚洲欧美一级| 国产主播精品在线| 亚洲一区二区三区午夜| 亚洲第一页自拍| 欧美制服丝袜第一页| 国产精品国产a| 亚洲免费观看高清在线观看 | 亚洲午夜在线视频| 欧美成人黑人xx视频免费观看| 亚洲图片在区色| 欧美日韩大片| 99精品国产在热久久| 欧美成年人视频网站欧美| 欧美一区二区视频网站| 国产精品免费福利| 亚洲欧美日韩成人高清在线一区| 亚洲精品美女免费| 欧美激情导航| 一区二区动漫| 亚洲三级国产| 欧美精品一区二区三区在线看午夜| 亚洲国产精彩中文乱码av在线播放| 久久xxxx| 欧美一区二区久久久| 国产亚洲aⅴaaaaaa毛片| 欧美一级艳片视频免费观看| 一区二区三区四区五区精品| 欧美日韩国产va另类| 洋洋av久久久久久久一区| 亚洲青涩在线| 国产精品sss| 欧美影院精品一区| 欧美在线播放高清精品| 国外成人网址| 欧美福利一区二区三区| 欧美风情在线| 亚洲免费视频网站| 一区二区三区国产在线| 亚洲免费观看高清在线观看 | 噜噜噜在线观看免费视频日韩| 久久国产综合精品| 亚洲国产欧美一区二区三区同亚洲| 男人的天堂亚洲| 欧美精品久久久久久久| 亚洲欧美日韩一区二区| 欧美中文字幕视频在线观看| 亚洲高清在线精品| 日韩一二在线观看| 国产欧美视频一区二区| 欧美成人精品一区二区三区| 欧美sm极限捆绑bd| 亚洲小视频在线观看| 久久成人精品无人区| 日韩天天综合| 欧美一区二区三区在线看| 亚洲国产高清一区| 亚洲新中文字幕| 亚洲高清视频在线| 亚洲一区二区在线播放| 亚洲欧洲精品成人久久奇米网| 亚洲视频在线观看| 亚洲国产日韩欧美综合久久| 亚洲一区二区三区四区视频 | 欧美主播一区二区三区美女 久久精品人| 午夜电影亚洲| 亚洲国产精品久久久| 亚洲欧美日韩精品久久亚洲区 | 91久久久一线二线三线品牌| 亚洲午夜电影在线观看| 在线精品一区二区| 亚洲一区二区欧美| 亚洲美女中出| 久久久午夜视频| 亚欧成人在线| 欧美高清不卡在线| 久久在线免费视频| 国产精品日本一区二区| 91久久线看在观草草青青| 国产欧美一区二区三区另类精品| 亚洲成色777777在线观看影院| 国产精品每日更新| 99av国产精品欲麻豆| 亚洲欧洲一区二区在线播放| 午夜精品美女久久久久av福利| aa亚洲婷婷| 欧美va亚洲va香蕉在线| 久久人人精品| 国产婷婷色一区二区三区在线| 日韩一区二区精品葵司在线| 亚洲精品九九| 美女网站在线免费欧美精品| 久久中文精品| 黄色成人在线网站| 欧美中在线观看| 久久精品夜色噜噜亚洲a∨| 久久国产精品久久精品国产| 欧美手机在线视频| 亚洲精品永久免费| 亚洲美女少妇无套啪啪呻吟| 麻豆91精品| 亚洲成色www8888| 亚洲国产va精品久久久不卡综合| 欧美中文字幕在线观看| 久久久人成影片一区二区三区观看 | 午夜精品视频| 久久久久久久成人| 狠狠入ady亚洲精品| 久久免费一区| 欧美成人嫩草网站| 亚洲日本视频| 欧美日韩亚洲一区二区三区| 日韩视频在线观看国产| 亚洲一区二区精品| 欧美午夜电影在线观看| 一区二区三区鲁丝不卡| 新狼窝色av性久久久久久| 国产日韩精品一区二区浪潮av| 亚洲欧美国产高清va在线播| 久久亚洲影音av资源网| 亚洲人成绝费网站色www| 欧美日韩裸体免费视频| 午夜在线视频一区二区区别| 久久国产日韩欧美| 亚洲人成免费| 国产精品久久77777| 久久国产免费看| 亚洲电影欧美电影有声小说| 一本色道88久久加勒比精品| 国产欧美日本一区视频| 美日韩精品免费观看视频| 日韩午夜在线播放| 久久精品视频免费播放| 亚洲肉体裸体xxxx137| 国产精品久久久久久久久久免费 | 亚洲精品国产精品乱码不99按摩 | 亚洲国产精品国自产拍av秋霞| 99视频精品全国免费| 国产美女扒开尿口久久久| 你懂的亚洲视频| 亚洲一区二区三区在线观看视频| 开元免费观看欧美电视剧网站| 99精品视频一区| 国产一区二区三区在线免费观看| 欧美高清自拍一区| 欧美伊人久久| 99国产精品久久久久久久成人热| 久久影音先锋| 欧美一区二区三区视频免费| 亚洲精美视频| 国产亚洲成年网址在线观看| 欧美刺激性大交免费视频| 国产精品一区二区男女羞羞无遮挡| 欧美国产成人在线| 午夜精品www| 亚洲精品系列| 狠狠色综合播放一区二区| 欧美午夜精品久久久| 欧美h视频在线| 久久精品av麻豆的观看方式| 亚洲夜晚福利在线观看| 日韩小视频在线观看| 亚洲国产老妈| 欧美成人免费视频| 久久综合色一综合色88| 欧美在线中文字幕|