'Ref' සහ 'out' යන වචන අතර වෙනස කුමක්ද?


905

වස්තුවක් සම්මත කිරීමට අවශ්‍ය තැන මම ශ්‍රිතයක් නිර්මාණය කරමි. අතර ඇති වෙනස කුමක්ද:

public void myFunction(ref MyClass someClass)

සහ

public void myFunction(out MyClass someClass)

මා භාවිතා කළ යුත්තේ කුමක්ද සහ ඇයි?


75
ඔබ: මම එය වෙනස් කළ හැකි බව ඒ නිසා වස්තුවක ගමන් කිරීමට අවශ්ය බව පෙනේ MyClassවිය හැකි බවට classවර්ගය, එනම්, සමුද්දේශ වර්ගය. එවැනි අවස්ථාවකදී, ඔබ පසු කරන වස්තුව myFunctionකිසිදු ref/ outයතුරු පදයකින් තොරව වෙනස් කළ හැකිය . එකම වස්තුවකට යොමු වන නව යොමු කිරීමක් myFunctionලැබෙනු ඇති අතර, එම වස්තුවට අවශ්‍ය ප්‍රමාණයට වෙනස් කළ හැකිය. මෙම වෙනස ඉඟි පද කරන්න වනු ඇත, එසේ නම් ඔහු ලැබුණු එකම එකම වස්තුව සඳහන්. එය වැදගත් වන්නේ වෙනත් වස්තුවකට යොමු කිරීම සඳහා යොමු කිරීම වෙනස් කළහොත් පමණි . refmyFunctionmyFunction
ජෙප් ස්ටිග් නීල්සන්

3
@ ඇන්තනි කොලෙසොව්ගේ වචන පරිපූර්ණ වූ විට මෙහි ව්‍යාකූල පිළිතුරු ප්‍රමාණය ගැන මම ප්‍රහේලිකාවක් වී සිටිමි.
o0 '.

බහුවිධ අගයන් ආපසු ලබා දීමට ඔබට ක්‍රමයක් අවශ්‍ය වූ විට පිටවීමේ ක්‍රමයක් ප්‍රකාශ කිරීම ප්‍රයෝජනවත් වේ. එක් තර්කයක් ශුන්‍යයට පැවරිය හැකිය. විකල්පයන් ලෙස අගයන් ආපසු ලබා දීමට මෙය ක්‍රම සක්‍රීය කරයි.
යෙව්ග්‍රාෆ් ඇන්ඩ්‍රෙවිච් ෂිවාගෝ

මෙහි උදාහරණය සමඟ පැහැදිලි කර ඇත එය වඩාත් තේරුම්ගත හැකිය :) dotnet-tricks.com/Tutorial/csharp/…
ප්‍රගීත්

2
Ep ජෙප්ස්ටිග් නීල්සන්ගේ ප්‍රකාශය, තාක්‍ෂණිකව, OP හි සත්‍ය ප්‍රශ්නයට (එකම) නිවැරදි පිළිතුරයි. එසේ ක්රමයක් බවට වස්තුවක් සම්මත කිරීමට මෙම ක්රමය වස්තුව වෙනස් කළ හැක , හුදෙක් අගය විසින් ක්රමයක් බවට වස්තුව (හැඩගැස්වීම) සමත්. වස්තුව පරාමිතිය හරහා ක්‍රමය තුළ වස්තුව වෙනස් කිරීම මුල් වස්තුව වෙනස් කරයි , ක්‍රමයට එහි වෙනම විචල්‍යයක් තිබුණද (එය එකම වස්තුවක් සඳහන් කරයි).
ඩේවිඩ් ආර් ට්‍රිබල්

Answers:


1177

refශ්‍රිතයට ඇතුළු වීමට පෙර වස්තුව ආරම්භ කර ඇති outබව සම්පාදකයාට පවසන අතර, ශ්‍රිතය තුළ වස්තුව ආරම්භ කරන බව සම්පාදකයාට පවසයි.

එබැවින් refදෙයාකාරයක් තිබියදීත්, outපිටත පමණි.


272
පිටතට විශේෂිත වූ තවත් සිසිල් දෙයක් නම් ශ්‍රිතයට පිටත පරාමිතියට පැවරිය යුතු බවයි. එය නියම නොකල ලෙස තැබීමට අවසර නැත.
ඩැනියෙල් අර්විකර්

7
'ref' අදාළ වන්නේ අගය වර්ගයට පමණක්ද? යොමු වර්ගය සෑම විටම ref මගින් සම්මත වන බැවින්.
දෝෂ සහිත

3
ඔව්. ව්‍යුහයන් ඇතුළුව වටිනාකම් වර්ග
රූන් ග්‍රිම්ස්ටැඩ්

17
දෝෂය: නැත, ref අගය වර්ග වලට පමණක් අදාළ නොවේ. ref / out යනු C / C ++ හි දර්ශක වැනි ය, ඒවා සෘජු වස්තුව වෙනුවට වස්තුවේ මතක පිහිටීම සමඟ (වක්‍රව C # වලින්) කටයුතු කරයි.
සොයුරා මට

53
@faulty: Counterintuitively, විමර්ශන වර්ග හැම විටම අගය විසින් C # දී, ඔබ ref විශේෂණයක් භාවිතා නොකරයි නම් සම්මත කර ඇත. ඔබ myval = somenewval සකසන්නේ නම්, බලපෑම පවතින්නේ එම ශ්‍රිත විෂය පථය තුළ පමණි. Ref keyword මඟින් ඔබට myval වෙනස් කිරීමට ඉඩ දෙනු ඇත.
ජේසන් ටෘ

545

මෙම refවිකරණකාරකය මාධ්යයන්:

  1. අගය දැනටමත් සකසා ඇති අතර
  2. ක්‍රමයට එය කියවා වෙනස් කළ හැකිය.

මෙම outවිකරණකාරකය මාධ්යයන්:

  1. අගය සකසා නැති අතර එය සැකසෙන තුරු ක්‍රමයට කියවිය නොහැක .
  2. නැවත පැමිණීමට පෙර ක්‍රමය එය සැකසිය යුතුය .

31
මෙම පිළිතුර වඩාත් පැහැදිලිව හා සංක්ෂිප්තව පැහැදිලි කරන්නේ ref යතුරුපදයට පටහැනිව පිටත යතුරු පදය භාවිතා කරන විට සම්පාදකයා විසින් පනවා ඇති සීමාවන් ය.
ආචාර්ය විලීගේ ආධුනිකයා

5
MSDN වෙතින්: භාවිතයට පෙර ref පරාමිතියක් ආරම්භ කළ යුතු අතර, සම්මත පරාමිතියක් සම්මත වීමට පෙර පැහැදිලිවම ආරම්භ කළ යුතු නැති අතර පෙර අගය නොසලකා හරිනු ලැබේ.
ශිව කුමාර්

1
සමග out, එය, ඒ ක්රමය මගින් නියම කර ඇති ක්රමය නම් පෙර එය ආරම්භනය කර තිබේ නම්, තියෙන්නේ කලින් එය, සියලු දී කියවිය හැකි ක්රමය තුළ? මා අදහස් කළේ, කැඳවුම් ක්‍රමයට තර්කයක් ලෙස ඇමතුම් ක්‍රමය එයට ලබා දුන් දේ කියවිය හැකිද?
Panzercrisis

3
Panzercrisis, "පිටතට" සඳහා, කැඳවූ ක්‍රමය එය දැනටමත් සකසා ඇත්නම් කියවිය හැකිය. නමුත් එය නැවත සැකසිය යුතුය.
robert jebakumar2

147

ටීපීඑස් වාර්තා පිළිබඳ සංදේශය ගැන ඩොම් පීටර්ගේ කුටියේ පෙන්වන බව කියමු.

ඩොම් ref තර්කයක් නම්, ඔහුට සංදේශයේ මුද්‍රිත පිටපතක් තිබේ.

ඩොම් බාහිර තර්කයක් නම්, ඔහු සමඟ රැගෙන යාම සඳහා ඔහු විසින් සංදේශයේ නව පිටපතක් මුද්‍රණය කරනු ඇත.


54
පීටර්ට එය වෙනස් කිරීමට හැකිවන පරිදි ඩොම් විසින් වාර්තාව පැන්සලෙන් ලියා ඇත
ඩීබ්ස්ටර්

6
Know ඔබ දන්නා ඩීබ්ස්ටර්, එම රූපකය කිසි විටෙකත් ඔබට කිසිවක් කර නැත, ඔබ එයට වධ දිය යුත්තේ ඇයි? ;)
මයිකල් බ්ලැක්බර්න්

21
විනෝදාත්මක නමුත් අධ්‍යාපනික, ස්ටැකෝවර් ප්‍රවාහයට මේ වගේ තවත් තනතුරු අවශ්‍යයි
ෆ්‍රෑන්ක් විසැගියෝ

2
කවුරුහරි මෙම පිළිතුර අඩ විහිළුවක් ලෙස දුටුවහොත් කරුණාකර "ඔෆිස් අවකාශය" චිත්‍රපටය නරඹන්න.
displayName

ඩොම් සහ පීටර්ස් ලොක්කා ඩොම් (තර්කයෙන් බැහැරව) සිටගෙන සිටින අතර, පීටර් ඩොම්ට මුද්‍රණය භාර දෙන තෙක් එය නැවත මුද්‍රණය කිරීමේ කටයුතු කිරීමට දෙදෙනාම බල කරයි
පැට්‍රික් ආර්ට්නර්

57

පැහැදිලි කිරීමකදී මම මගේ අත උත්සාහ කරමි:

මම හිතන්නේ අපි තේරුම් ගත්තා වටිනාකම් වර්ග නිවැරදිව ක්‍රියා කරන්නේ කෙසේද? අගය වර්ග (int, long, struct ආදිය). Ref විධානයක් නොමැතිව ඔබ ඒවා ශ්‍රිතයකට යවන විට එය දත්ත පිටපත් කරයි . ශ්‍රිතයේ එම දත්ත සඳහා ඔබ කරන ඕනෑම දෙයක් බලපාන්නේ පිටපතට මිස මුල් පිටපතට නොවේ. Ref විධානය මඟින් ACTUAL දත්ත යවන අතර ඕනෑම වෙනස්කමක් ශ්‍රිතයෙන් පිටත දත්ත වලට බලපායි.

අවුල් සහගත කොටස වෙත යොමු වන්න, යොමු වර්ග:

යොමු වර්ගයක් නිර්මාණය කිරීමට ඉඩ දෙමු:

List<string> someobject = new List<string>()

ඔබ යම්කිසි දෙයක් අලුත් කළ විට , කොටස් දෙකක් සාදනු ලැබේ:

  1. කිසියම් වස්තුවක් සඳහා දත්ත රඳවා තබා ඇති මතක කොටස .
  2. එම දත්ත කාණ්ඩයට යොමු කිරීමක් (දර්ශකය).

දැන් ඔබ කිසියම් වස්තුවක් යොමු නොකර ක්‍රමයකට යවන විට එය යොමු දර්ශකය පිටපත් කරයි , දත්ත නොවේ. එබැවින් ඔබට දැන් මෙය තිබේ:

(outside method) reference1 => someobject
(inside method)  reference2 => someobject

එකම වස්තුවට යොමු වන යොමු දෙකක්. යොමු අංක 2 භාවිතා කරමින් ඔබ කිසියම් වස්තුවක් මත දේපලක් වෙනස් කරන්නේ නම්, එය යොමු අංක 1 මඟින් පෙන්වා ඇති දත්ත වලටම බලපායි.

 (inside method)  reference2.Add("SomeString");
 (outside method) reference1[0] == "SomeString"   //this is true

ඔබ යොමු 2 අහෝසි කළහොත් හෝ එය නව දත්ත වෙත යොමු කළහොත් එය යොමු අංක 1 ට හෝ දත්ත යොමු 1 වෙත යොමු නොවේ.

(inside method) reference2 = new List<string>();
(outside method) reference1 != null; reference1[0] == "SomeString" //this is true

The references are now pointing like this:
reference2 => new List<string>()
reference1 => someobject

දැන් ඔබ එවන විට සිද්ධ වෙන්නේ මොකක්ද someobject ගැනීමට ක්රමයක් ref විසින්? මෙම සත්ය යොමු කිරීමට someobject ක්රමයක් ලෙස යවයි. එබැවින් ඔබට දැන් ඇත්තේ දත්ත පිළිබඳ එක් සඳහනක් පමණි:

(outside method) reference1 => someobject;
(inside method)  reference1 => someobject;

නමුත් මෙයින් අදහස් කරන්නේ කුමක්ද? එය ප්‍රධාන කාරණා දෙකක් හැරුණු විට කිසියම් වස්තුවක් යොමු කිරීමෙන් නොවේ.

1) ඔබ ක්‍රමවේදය තුළ ඇති යොමුව අහෝසි කළ විට එය ක්‍රමයට පිටතින් ඇති එක අහෝසි කරයි.

 (inside method)  reference1 = null;
 (outside method) reference1 == null;  //true

2) ඔබට දැන් යොමු කිරීම සම්පූර්ණයෙන්ම වෙනස් දත්ත ස්ථානයකට යොමු කළ හැකි අතර ශ්‍රිතයෙන් පිටත යොමු කිරීම දැන් නව දත්ත ස්ථානයට යොමු වේ.

 (inside method)  reference1 = new List<string>();
 (outside method) reference1.Count == 0; //this is true

ඔබ අදහස් කළේ සියල්ලට පසු (ref අවස්ථාවෙහිදී) ඇත්තේ දත්ත සඳහා එක් සඳහනක් පමණක් වන නමුත් ඒ සඳහා අන්වර්ථ දෙකක්. හරිද?
සාදික්

3
පැහැදිලි පැහැදිලි කිරීම සඳහා ඉහළට. නමුත් මම එය අතර වෙනස පැහැදිලි නැහැ ලෙස, මේ ප්රශ්නයට පිළිතුරු නැත හිතන්නේ refහා outපරාමිතීන්.
ජොයිස් බාබු

1
අරුම පුදුම. outමූල පදය සඳහා ඔබට එයම පැහැදිලි කළ හැකිද?
අසිෆ් මුෂ්තාක්

28

ref ඇතුලත සහ පිටත ඇත.

outඔබේ අවශ්‍යතාවයන් සඳහා ප්‍රමාණවත් වන ඕනෑම තැනක ඔබ මනාපයෙන් භාවිතා කළ යුතුය .


පිළිගත් පිළිතුර ලෙස දිශානුගත හා නිෂ් less ල නොසලකා හරින ලද වටිනාකම් වර්ග ආපසු නොයන්නේ නම්.
කෙනී

@kenny: කරුණාකර ඔබට ටිකක් පැහැදිලි කර ගත හැකිද - එනම්, පිළිතුරේ ආත්මය පවත්වා ගැනීමට ඔබ වෙනස් කරන්නේ කුමන වචනද? මගේ පිළිතුර නවකයකුගේ පිස්සු අනුමානයක් නොවේ, නමුත් ඔබේ අදහස් දැක්වීමේ ඉක්මන් (වෙහෙස, යතුරු ලියනය) එය උපකල්පනය කරයි. අවම වචන ගණන සමඟ වෙනස ගැන සිතීමේ ක්‍රමයක් සැපයීම අරමුණයි.
රූබන් බාර්ටලින්ක්

(BTW මම ඔබට එය ප්රයෝජනවත් ඔබගේ පැහැදිලි කිරීමක් එම සංකල්ප ගැන සඳහන් කිරීමට සොයා ගත යුතුය අගය වර්ග, සමුද්දේශ වර්ග, සමුද්දේශ විසින් පසුකර යන, වටිනාකම පසුකර යන, COM හා C ++ හුරු ඉන්නේ)
රූබන් Bartelink

1
වස්තු යොමු කිරීම් අගය අනුව සම්මත වේ ("ref" හෝ "out" යතුරු පදය භාවිතා කරන විට හැර). වස්තු හැඳුනුම් අංක ලෙස සිතන්න. පංති විචල්‍යයක් "වස්තුව # 1943" රඳවාගෙන යමෙක් එම විචල්‍යය අගය අනුව දෛනිකව සම්මත කරන්නේ නම්, එම චර්යාවට වස්තුව # 1943 ට වෙනස්කම් කළ හැකි නමුත් විචල්‍ය ලක්ෂ්‍යය "වස්තුව # 1943" හැර වෙනත් දෙයකට යොමු කළ නොහැක. විචල්‍යය යොමු කිරීම මඟින් සම්මත කර ඇත්නම්, දෛනිකව විචල්‍ය ලක්ෂ්‍යය "වස්තුව # 5441" රඳවා තබා ගත හැකිය.
සුපර් කැට්

1
up සුපර්කැට්: ref vs val (සහ මෙම පසු විපරම් නිර්වින්දනය) පිළිබඳ ඔබේ පැහැදිලි කිරීමට මම කැමතියි. මම හිතන්නේ කෙනීට මේ කිසිවක් පැහැදිලි කිරීමට අවශ්‍ය නැත, (සාපේක්ෂව) ඔහුගේ අදහස් මෙන් ව්‍යාකූල විය. මම හිතන්නේ අපි හැමෝටම මේ ගොඩ්ඩෑම් අදහස් ඉවත් කරන්න පුළුවන්. මේ සියලු විකාර වලට මූලික හේතුව පෙනෙන්නේ කෙනී මගේ පිළිතුර වැරදියට කියවා ඇති අතර එකතු කළ යුතු / ඉවත් කළ යුතු / ප්‍රතිස්ථාපනය කළ යුතු එක වචනයක්වත් පෙන්වා දී නැත. අප තිදෙනාගෙන් කිසිවෙකු අප දැනටමත් නොදැන සිටි සාකච්ඡාවෙන් කිසිවක් ඉගෙන ගෙන නැති අතර අනෙක් පිළිතුරට හාස්‍යජනක සංඛ්‍යාවක් ඇත.
රූබන් බාර්ටලින්ක්

18

පිටතට:

C # හි, ක්‍රමයකට ආපසු ලබා දිය හැක්කේ එක් අගයක් පමණි. ඔබ එකකට වඩා වැඩි වටිනාකමක් ලබා දීමට කැමති නම්, ඔබට පිටත යතුරු පදය භාවිතා කළ හැකිය. පිටත විකරණකාරකය ආපසු-යොමු-යොමු ලෙස ආපසු එයි. සරලම පිළිතුර නම් ක්‍රමයෙන් වටිනාකම ලබා ගැනීම සඳහා “පිටතට” යන පදය භාවිතා කිරීමයි.

  1. ඇමතුම් ශ්‍රිතයේ අගය ආරම්භ කිරීමට ඔබට අවශ්‍ය නැත.
  2. ඔබ කැඳවූ ශ්‍රිතයේ අගය පැවරිය යුතුය, එසේ නොමැතිනම් සම්පාදකයා දෝෂයක් වාර්තා කරයි.

ref:

C # හි, ඔබ ක්‍රම පරාමිතියට තර්කයක් ලෙස int, float, double ආදී අගයන් වර්ගයක් සම්මත කළ විට එය අගය මගින් සම්මත වේ. එමනිසා, ඔබ පරාමිති අගය වෙනස් කරන්නේ නම්, එය ක්‍රම ඇමතුමේ තර්කයට බලපාන්නේ නැත. නමුත් ඔබ පරාමිතිය “ref” යතුරු පදයෙන් සලකුණු කළහොත් එය සත්‍ය විචල්‍යයෙන් පිළිබිඹු වේ.

  1. ඔබ ශ්‍රිතය ඇමතීමට පෙර විචල්‍යය ආරම්භ කළ යුතුය.
  2. ක්‍රමයේ ref පරාමිතියට කිසිදු අගයක් පැවරීම අනිවාර්ය නොවේ. ඔබ අගය වෙනස් නොකරන්නේ නම්, එය “ref” ලෙස සලකුණු කිරීමේ අවශ්‍යතාවය කුමක්ද?

"C # හි, ක්‍රමයකට ආපසු එවිය හැක්කේ එක් අගයක් පමණි. ඔබ එක් අගයකට වඩා ආපසු ලබා දීමට කැමති නම්, ඔබට පිටත යතුර භාවිතා කළ හැකිය." ප්‍රතිලාභ අගය සඳහා අපට "ref" භාවිතා කළ හැකිය. අපට ක්‍රමයකින් බහුවිධ අගයන් ආපසු ලබා දීමට අවශ්‍ය නම් අපට ref සහ out යන දෙකම භාවිතා කළ හැකිද?
නෙඩ්

1
C # 7 හි ඔබට ValueTuples සමඟ බහු අගයන් ලබා දිය හැකිය.
ඉමාන් බහ්රම්පූර්

13

බල්ලා දිගු කිරීම, බළලා උදාහරණය. Ref සමඟ දෙවන ක්‍රමය අමතන්නා විසින් යොමු කරන ලද වස්තුව වෙනස් කරයි. එබැවින් "බළලා" !!!

    public static void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog". 
        Bar(ref myObject);
        Console.WriteLine(myObject.Name); // Writes "Cat". 
    }

    public static void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

    public static void Bar(ref MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

8

ඔබ යොමු වර්ගයක (පංතියක) පසු වන බැවින් භාවිතයේ අවශ්‍යතාවයක් නොමැත, refමන්ද පෙරනිමියෙන් සත්‍ය වස්තුව පිළිබඳ සඳහනක් පමණක් සම්මත වන අතර එම නිසා ඔබ සැමවිටම යොමු පිටුපස ඇති වස්තුව වෙනස් කරයි.

උදාහරණයක්:

public void Foo()
{
    MyClass myObject = new MyClass();
    myObject.Name = "Dog";
    Bar(myObject);
    Console.WriteLine(myObject.Name); // Writes "Cat".
}

public void Bar(MyClass someObject)
{
    someObject.Name = "Cat";
}

ඔබ පන්තියක සමත් වන තාක් කල් refඔබේ ක්‍රමය තුළ ඇති වස්තුව වෙනස් කිරීමට අවශ්‍ය නම් ඔබ භාවිතා කළ යුතු නොවේ .


5
මෙය ක්‍රියාත්මක වන්නේ නව වස්තුවක් නිර්මාණය කර ආපසු ලබා නොදුනහොත් පමණි. නව වස්තුවක් නිර්මාණය කළ විට, පැරණි වස්තුව පිළිබඳ සඳහන නැති වේ.
etsuba

8
මෙය වැරදියි - පහත සඳහන් දෑ උත්සාහ කරන්න: ක්‍රියාත්මක someObject = nullකිරීමට Barඅවසානයට එක් කරන්න. ඔබගේ කේතය හොඳින් ක්‍රියාත්මක Barවන්නේ නිදසුන පිළිබඳ සඳහනක් පමණක් අවලංගු කර ඇති බැවිනි. දැන් වෙනස් Barකර Bar(ref MyClass someObject)නැවත ක්‍රියාත්මක කරන්න - ඔබට උදාහරණය පිළිබඳ සඳහනක් ද අවලංගු කර ඇති NullReferenceExceptionනිසා ඔබට එය ලැබෙනු Fooඇත.
කීත්

8

refoutපහත සඳහන් වෙනස්කම් හැර ඒ හා සමානව හැසිරෙන්න.

  • refභාවිතයට පෙර විචල්‍යය ආරම්භ කළ යුතුය. outපැවරුමකින් තොරව විචල්‍යය භාවිතා කළ හැකිය
  • outපරාමිතිය එය භාවිතා කරන ශ්‍රිතය මගින් නියම නොකළ අගයක් ලෙස සැලකිය යුතුය. එබැවින්, අපට outඇමතුම් කේතයේ ආරම්භක පරාමිතිය භාවිතා කළ හැකිය , නමුත් ශ්‍රිතය ක්‍රියාත්මක වන විට අගය නැති වේ.

8

ආදර්ශයෙන් ඉගෙන ගන්නා අයට (මා වැනි) ඇන්තනි කොලෙසොව් පවසන දේ මෙන්න .

කාරණය නිදර්ශනය කිරීම සඳහා මම ref, out, සහ වෙනත් උදාහරණ කිහිපයක් නිර්මාණය කර ඇත්තෙමි. මම හොඳම භාවිතයන් ආවරණය නොකරමි, වෙනස්කම් තේරුම් ගැනීමට උදාහරණ පමණි.

https://gist.github.com/2upmedia/6d98a57b68d849ee7091


6

"බේකර්"

එයට හේතුව පළමුවැන්න ඔබේ නූල් යොමුව “බේකර්” වෙත යොමු කිරීමයි. ඔබ එය ref යතුරුපදය හරහා සම්මත කළ නිසා (=> නූලකට යොමු කිරීමකට යොමු කිරීම) යොමු කිරීම වෙනස් කළ හැකිය. දෙවන ඇමතුමට නූලට යොමු කිරීමේ පිටපතක් ලැබේ.

නූල් මුලින් යම් ආකාරයක විශේෂ පෙනුමක්. නමුත් නූල් යනු යොමු පන්තියක් පමණක් වන අතර ඔබ අර්ථ දක්වන්නේ නම්

string s = "Able";

s යනු “Able” පා text ය අඩංගු නූල් පන්තියකට යොමු කිරීමකි! එකම විචල්‍යයට තවත් පැවරුමක්

s = "Baker";

මුල් නූල වෙනස් නොකරන නමුත් නව අවස්ථාවක් නිර්මාණය කර එම අවස්ථාව වෙත යොමු වීමට ඉඩ දෙන්න!

පහත දැක්වෙන කුඩා කේත උදාහරණය සමඟ ඔබට එය උත්සාහ කළ හැකිය:

string s = "Able";
string s2 = s;
s = "Baker";
Console.WriteLine(s2);

ඔබ බලාපොරොත්තු වන්නේ මොනවද? ඔබට ලැබෙන දෙය තවමත් "හැකියාව" වන්නේ ඔබ s හි මුල් උදාහරණයට යොමු කරන අතරම වෙනත් අවස්ථාවකට යොමු කිරීම ය.

සංස්කරණය කරන්න: නූල් ද වෙනස් කළ නොහැකි ය, එයින් අදහස් කරන්නේ දැනට පවතින නූල් නිදසුනක් වෙනස් කරන ක්‍රමවේදයක් හෝ දේපලක් නොමැති බවයි (ඔබට ලේඛනයේ එකක් සොයා ගැනීමට උත්සාහ කළ හැකි නමුත් ඔබට වරල් කිසිවක් නොලැබේ :-)). සියලුම නූල් හැසිරවීමේ ක්‍රම නව සංගීත අවස්ථාවක් ලබා දෙයි! (StringBuilder පන්තිය භාවිතා කරන විට ඔබට බොහෝ විට වඩා හොඳ කාර්ය සාධනයක් ලැබෙන්නේ එබැවිනි)


1
හරියටම. එබැවින් "ඔබ යොමු වර්ගයක (පංතියක) සමත් වන බැවින් අවශ්‍යතාවය භාවිතා කිරීම අවශ්‍ය නොවේ" යනුවෙන් පැවසීම තදින්ම සත්‍ය නොවේ.
පෝල් මිචෙල්

න්‍යාය අනුව එසේ පැවසීම නිවැරදියි, මන්ද ඔහු නූල් මත කළ නොහැකි “එය වෙනස් කළ හැකි වන පරිදි” ලියා ඇති බැවිනි. නමුත් වෙනස් කළ නොහැකි වස්තූන් නිසා "ref" සහ "out" යොමු වර්ග සඳහාද ඉතා ප්‍රයෝජනවත් වේ! (.නෙට් හි වෙනස් කළ නොහැකි පන්ති රාශියක් අඩංගු වේ!)
mmmmmmmm

ඔව්, ඔබ හරි. නූල් වැනි වෙනස් කළ නොහැකි වස්තූන් ගැන මම නොසිතුවෙමි.
ඇල්බික්

1
හොඳයි, මෙය LQP හි දැකීමට ඇති ප්‍රහේලිකාවක්, නිසැකවම; එය වෙනත් අදහස් දැක්වීමකට දීර් and හා ගැඹුරු ප්‍රතිචාරයක් ලෙස පෙනෙන්නට තිබීම හැර එහි කිසිදු වැරැද්දක් නොමැත (මුල් ප්‍රශ්නයේ දී ඒබල් සහ බේකර් එහි කිසිදු සංශෝධනයක සඳහන් නොවන බැවින්) මෙය සංසදයක් මෙන් ය. මම හිතන්නේ එය ඇත්ත වශයෙන්ම වර්ග කර නැත.
නේතන් ටග්ගි

6

ref යන්නෙන් අදහස් වන්නේ ref පරාමිතියේ අගය දැනටමත් සකසා ඇති බැවින් ක්‍රමයට එය කියවා වෙනස් කළ හැකිය. පරාමිතිකයේ අගය ආරම්භ කිරීම සඳහා අමතන්නා වගකිව යුතු යැයි පැවසීම ref යතුර භාවිතා කිරීම සමාන වේ.


අවුට් සම්පාදකයාට පවසන්නේ වස්තුව ආරම්භ කිරීම ශ්‍රිතයේ වගකීම බවයි, ශ්‍රිතය පිටත පරාමිතියට පැවරිය යුතුය. එය නියම නොකල ලෙස තැබීමට අවසර නැත.


5

පිටතට: ශ්‍රිතයකින් එක් අගයක් පමණක් ලබා දීම සඳහා ආපසු ප්‍රකාශයක් භාවිතා කළ හැකිය. කෙසේ වෙතත්, ප්‍රතිදාන පරාමිතීන් භාවිතා කිරීමෙන් ඔබට ශ්‍රිතයකින් අගයන් දෙකක් ආපසු ලබා දිය හැකිය. නිමැවුම් පරාමිතීන් යොමු පරාමිතීන් හා සමාන වේ, ඒවා දත්ත වලට වඩා ක්‍රමයෙන් පිටතට මාරු කිරීම හැර.

පහත උදාහරණයෙන් මෙය පැහැදිලි වේ:

using System;

namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void getValue(out int x )
      {
         int temp = 5;
         x = temp;
      }

      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* local variable definition */
         int a = 100;

         Console.WriteLine("Before method call, value of a : {0}", a);

         /* calling a function to get the value */
         n.getValue(out a);

         Console.WriteLine("After method call, value of a : {0}", a);
         Console.ReadLine();

      }
   }
}

ref: යොමු පරාමිතිය යනු විචල්‍යයක මතක පිහිටීමකට යොමු කිරීමකි. ඔබ පරාමිතීන් යොමු කිරීමෙන් සම්මත අගයන් මෙන් නොව, මෙම පරාමිතීන් සඳහා නව ගබඩා ස්ථානයක් නිර්මාණය නොවේ. විමර්ශන පරාමිතීන් ක්‍රමයට සපයනු ලබන සත්‍ය පරාමිතීන් හා සමාන මතක ස්ථානයක් නිරූපණය කරයි.

C # හි, ඔබ ref යතුරු පදය භාවිතා කරමින් විමර්ශන පරාමිතීන් ප්‍රකාශ කරයි. පහත උදාහරණයෙන් මෙය පෙන්නුම් කරයි:

using System;
namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void swap(ref int x, ref int y)
      {
         int temp;

         temp = x; /* save the value of x */
         x = y;   /* put y into x */
         y = temp; /* put temp into y */
       }

      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* local variable definition */
         int a = 100;
         int b = 200;

         Console.WriteLine("Before swap, value of a : {0}", a);
         Console.WriteLine("Before swap, value of b : {0}", b);

         /* calling a function to swap the values */
         n.swap(ref a, ref b);

         Console.WriteLine("After swap, value of a : {0}", a);
         Console.WriteLine("After swap, value of b : {0}", b);

         Console.ReadLine();

      }
   }
}

5

සංක්ෂිප්ත පිළිතුරක් සොයන අයට.

දෙකම refසහ outමූල පද පසුකර යාමට භාවිතා කරයි reference.


ක විචල්ය refඉඟි පද අගය තිබිය යුතුය හෝ වස්තුවක් හෝ යොමු කළ යුතුය null පෙර එහි සම්මත.


මෙන් නොව ref, ක විචල්ය outඉඟි පද අගය තිබිය යුතුය හෝ වස්තුවක් හෝ යොමු කළ යුතුය null පසු එහි සම්මත මෙන්ම අගය හෝ වස්තුවක් වෙත යොමු කිරීමට කිසිදු අවශ්යතාවයක් පෙර ගමන්.


4

C ++ හි මෙන් යොමු කිරීම් සහ දර්ශකයන් පසු කිරීම වැනි ref සහ out වැඩ.

Ref සඳහා, තර්කය ප්‍රකාශ කර ආරම්භ කළ යුතුය.

පිටතට යාම සඳහා, තර්කය ප්‍රකාශ කළ යුතු නමුත් ආරම්භ කිරීමට හෝ නොවීමට ඉඩ ඇත

        double nbr = 6; // if not initialized we get error
        double dd = doit.square(ref nbr);

        double Half_nbr ; // fine as passed by out, but inside the calling  method you initialize it
        doit.math_routines(nbr, out Half_nbr);

1
ඔබට විචල්ය පේළියක් ප්‍රකාශ කළ හැකිය : out double Half_nbr.
සෙබස්තියන් හොෆ්මන්

4

කර්තෘ කාලය:

(1) අපි ඇමතුම් ක්‍රමය නිර්මාණය කරමු Main()

(2) එය ලැයිස්තු වස්තුවක් නිර්මාණය කරයි (එය යොමු වර්ගයේ වස්තුවකි) එය විචල්යයේ ගබඩා කරයි myList.

public sealed class Program 
{
    public static Main() 
    {
        List<int> myList = new List<int>();

ධාවන කාලය තුළ:

(3) ධාවන කාලය ලිපිනය ගබඩා කිරීම සඳහා ප්‍රමාණවත් තරම් පළල # 00 හි මතකය වෙන් කරයි (# 00 = myList, විචල්‍ය නම් ඇත්ත වශයෙන්ම මතක ස්ථාන සඳහා අන්වර්ථ නාමයන් බැවින්)

(4) ධාවන කාලය මතක ස්ථානයේ #FF හි ගොඩවල් මත ලැයිස්තු වස්තුවක් නිර්මාණය කරයි (මෙම ලිපිනයන් සියල්ලම නිදසුනක් ලෙස වේ)

(5) ධාවන වේලාව පසුව වස්තුවේ ආරම්භක ලිපිනය #FF # 00 හි ගබඩා කරයි (හෝ වචන වලින් කිවහොත්, ලැයිස්තු වස්තුව යොමු කිරීම දර්ශකයේ ගබඩා කරයි myList)

කර්තෘ කාලය වෙත ආපසු:

(6) ඉන්පසු අපි ලැයිස්තු වස්තුව myParamListකැඳවූ ක්‍රමයට තර්කයක් ලෙස සම්මත කර modifyMyListඑයට නව ලැයිස්තු වස්තුවක් පවරමු

List<int> myList = new List<int>();

List<int> newList = ModifyMyList(myList)

public List<int> ModifyMyList(List<int> myParamList){
     myParamList = new List<int>();
     return myParamList;
}

ධාවන කාලය තුළ:

(7) ධාවන කාලය ඇමතුම් ක්‍රමය ඇමතුම් ක්‍රමය ආරම්භ කරන අතර එහි කොටසක් ලෙස පරාමිති වර්ගය පරීක්ෂා කරයි.

(8) විමර්ශන වර්ගය සොයාගත් පසු, එය පරාමිති විචල්‍යය අන්වර්ථ කිරීම සඳහා # 04 හි සිරස් මතකයක් වෙන් කරයි myParamList.

(9) ඉන්පසු එය #FF අගය ද ගබඩා කරයි.

.

# 00 හි ලිපිනය වෙනස් නොවන අතර #FF වෙත යොමු කිරීම රඳවා තබා ගනී (නැතහොත් මුල් myListදර්ශකය බාධා නොකෙරේ).


මෙම ref මූල පදය (8) සඳහා ධාවන කේතය උත්පාදනය මඟ කිරීමට සම්පාදක උපදෙස් හා (9) ක්රමය පරාමිතීන් සඳහා ගොඩක් වෙන් වනු ඇත, ඉන් අදහස් වන්නේ. එය #FF හි වස්තුව මත ක්‍රියා කිරීමට මුල් # 00 දර්ශකය භාවිතා කරයි. මුල් දර්ශකය ආරම්භ කර නොමැති නම්, විචල්‍යය ආරම්භ කර නොමැති බැවින් එය ඉදිරියට යා නොහැකි බවට පැමිණිලි කිරීම ක්‍රියාත්මක වේ.

මෙම සිදු ඉඟි පද එච්චරමයි (9) පැවති සුළු වෙනස් කිරීම් සහිත ref ලෙස එම වන වන සම්පාදක උපදෙස් හා (10). සම්පාදකයා විසින් තර්කය ආරම්භ නොකිරීමට අපේක්ෂා කරන අතර (8), (4) සහ (5) සමඟ ගොඩගැසී ඇති වස්තුවක් නිර්මාණය කිරීම සහ එහි ආරම්භක ලිපිනය තර්ක විචල්‍යය තුළ ගබඩා කිරීම. ආරම්භ නොකළ දෝෂයක් විසි නොවන අතර කලින් ගබඩා කර තිබූ කිසිදු සඳහනක් නැති වී යයි.


3

හොඳින් පන්තියේ විවිධ උදාහරණයක් කිරීමට නැවත පැවරීම තව කෙනෙකුගේ විචල්ය කිරීමට ඔබට ඉඩ තරම්, ආදිය බහු වටිනාකම් නැවත භාවිතා refහෝ outවෙන කෙනෙක් ඔබ ඔවුන්ගෙන් අවශ්ය දේ දැන ගැනීමට ඉඩ සලස්වන සහ ඔබ ඔවුන් සපයන විචල්ය සමග අදහස්

  • ඔබට අවශ්‍ය නැත, ref නැතහොත් outඔබ කිරීමට යන්නේ තර්කයේ සම්මත කර ඇති උදාහරණය තුළ ඇති දේවල් වෙනස් කිරීම පමණි .MyClasssomeClass

    • මෙම ඉල්ලා ක්රමය වගේ වෙනස්කම් දකිනු ඇත someClass.Message = "Hello World"ඔබ භාවිතා යන්න ref, outහෝ කිසිවක්
    • someClass = new MyClass()ඇතුළත ලිවීම ක්‍රමයේ විෂය පථයට පමණක් myFunction(someClass)පෙනෙන වස්තුව මාරු කරයි . ඇමතුම් ක්‍රමය තවමත් එය නිර්මාණය කර ඔබේ ක්‍රමයට ලබා දුන් මුල් අවස්ථාව ගැන දනීsomeClassmyFunctionMyClass
  • ඔබට අවශ්‍ය නම් refහෝ outඔබ someClassනව වස්තුවක් සඳහා හුවමාරු කර ගැනීමට අදහස් කරන්නේ නම් සහ ඔබේ වෙනස දැකීමට ඇමතුම් ක්‍රමයට අවශ්‍ය නම්

    • someClass = new MyClass()ඇතුළත ලිවීමෙන් myFunction(out someClass)හැඳින්වූ ක්‍රමය මඟින් දකින වස්තුව වෙනස් වේmyFunction

වෙනත් ක්‍රමලේඛකයින් සිටී

ඔවුන්ගේ දත්ත සමඟ ඔබ කුමක් කරන්නදැයි ඔවුන්ට දැන ගැනීමට අවශ්‍යය. ඔබ මිලියන ගණනක් සංවර්ධකයින් භාවිතා කරන පුස්තකාලයක් ලියන බව සිතන්න. ඔවුන් ඔබේ ක්‍රමවේදයන් අමතන විට ඔවුන්ගේ විචල්‍යයන් සමඟ ඔබ කුමක් කරන්නදැයි ඔවුන් දැන ගැනීමට ඔබට අවශ්‍යය

  • භාවිතා refකිරීම ප්‍රකාශයක් කරයි "ඔබ මගේ ක්‍රමය අමතන විට යම් අගයකට පවරා ඇති විචල්‍යයක් පසු කරන්න. මගේ ක්‍රමවේදය තුළ එය වෙනත් දෙයක් සඳහා සම්පූර්ණයෙන්ම වෙනස් කළ හැකි බව මතක තබා ගන්න. ඔබේ විචල්‍යය පැරණි වස්තුව වෙත යොමු වනු ඇතැයි අපේක්ෂා නොකරන්න මම ඉවර වුනාම "

  • භාවිතා outකිරීම "මගේ ක්‍රමයට ස්ථාන දරණ විචල්‍යයක් ලබා දෙන්න. එහි වටිනාකමක් තිබේද නැද්ද යන්න ගැටළුවක් නොවේ; එය නව අගයකට පැවරීමට සම්පාදකයා මට බල කරයි. ඔබේ වස්තුව පෙන්වා දුන් වස්තුව මම සහතික කරමි. ඔබ මගේ ක්‍රමයට කතා කිරීමට පෙර විචල්‍යය, මා අවසන් වන විට වෙනස් වේ

මාර්ගය වන විට, සී # 7.2 හි අ in නවීකරණයක් ද ඇත

එමඟින් සම්මත වූ අවස්ථාව වෙනත් අවස්ථාවකට මාරු කිරීමෙන් ක්‍රමය වළක්වයි. එම මිලියන සංඛ්‍යාත සංවර්ධකයින්ට "ඔබේ මුල් විචල්‍ය යොමුව මට එවන්න, ඔබ පරිස්සමින් සකස් කළ දත්ත වෙනත් දෙයකට මාරු නොකරන බවට මම පොරොන්දු වෙමි" යනුවෙන් සිතන්න. inසමහර සුවිශේෂතා ඇති අතර, සමහර අවස්ථාවලදී in intසම්පාදකයෙකු සමඟ ඔබේ කෙටි අනුකූලතාව ඇති කිරීම සඳහා ව්‍යංග පරිවර්තනයක් අවශ්‍ය විය හැකිය. එය තාවකාලිකව int එකක් සාදනු ඇත, ඔබේ කෙටිකතාව පුළුල් කර, යොමු කිරීමෙන් එය අවසන් කර අවසන් කරයි. එයට මෙය කළ හැක්කේ ඔබ එය අවුල් නොකරන බව ප්‍රකාශ කර ඇති බැවිනි.


මයික්‍රොසොෆ්ට් මෙය .TryParseසිදු කළේ සංඛ්‍යාත්මක වර්ගවල ක්‍රම සමඟ ය :

int i = 98234957;
bool success = int.TryParse("123", out i);

පරාමිතිය outඔවුන් සක්‍රීයව මෙහි ප්‍රකාශ කරන බැවින් සලකුණු කිරීමෙන් "අපි අනිවාර්යයෙන්ම ඔබගේ වෙහෙස මහන්සි වී නිර්මාණය කරන ලද 98234957 අගය වෙනත් දෙයක් සඳහා වෙනස් කරන්නෙමු"

ඇත්ත වශයෙන්ම, වටිනාකම් වර්ග විග්‍රහ කිරීම වැනි දේ සඳහා ඔවුන් කළ යුතුව ඇත්තේ, වෙනත් දෙයක් සඳහා අගය වර්ගය මාරු කිරීමට විග්‍රහ කිරීමේ ක්‍රමයට ඉඩ නොදුනහොත් එය එතරම් සාර්ථක නොවනු ඇති බවයි .. නමුත් සමහර විට ව්‍යාජ ක්‍රමයක් ඇතැයි සිතන්න ඔබ නිර්මාණය කරන පුස්තකාලය:

public void PoorlyNamedMethod(out SomeClass x)

ඔබට එය දැක ගත හැකි අතර out, ඒ අනුව ඔබ සංඛ්‍යා බිඳීමට පැය ගණනක් ගත කරන්නේ නම්, පරිපූර්ණ සොම් ක්ලාස් නිර්මාණය කරන බව ඔබට දැනගත හැකිය:

SomeClass x = SpendHoursMakingMeAPerfectSomeClass();
//now give it to the library
PoorlyNamedMethod(out x);

හොඳයි, එය කාලය නාස්ති කිරීමක් වන අතර, එම පරිපූර්ණ පන්තිය සෑදීමට එම පැය සියල්ලම ගත විය. එය අනිවාර්යයෙන්ම ඉවතට විසිවී ගොස් PolylyNamedMethod මගින් ප්‍රතිස්ථාපනය වේ


3

බොහෝ විශිෂ්ට පැහැදිලි කිරීම් නිදර්ශනය කිරීම සඳහා, මම පහත කොන්සෝල යෙදුම සංවර්ධනය කළෙමි:

using System;
using System.Collections.Generic;

namespace CSharpDemos
{
  class Program
  {
    static void Main(string[] args)
    {
      List<string> StringList = new List<string> { "Hello" };
      List<string> StringListRef = new List<string> { "Hallo" };

      AppendWorld(StringList);
      Console.WriteLine(StringList[0] + StringList[1]);

      HalloWelt(ref StringListRef);
      Console.WriteLine(StringListRef[0] + StringListRef[1]);

      CiaoMondo(out List<string> StringListOut);
      Console.WriteLine(StringListOut[0] + StringListOut[1]);
    }

    static void AppendWorld(List<string> LiStri)
    {
      LiStri.Add(" World!");
      LiStri = new List<string> { "¡Hola", " Mundo!" };
      Console.WriteLine(LiStri[0] + LiStri[1]);
    }

    static void HalloWelt(ref List<string> LiStriRef)
     { LiStriRef = new List<string> { LiStriRef[0], " Welt!" }; }

    static void CiaoMondo(out List<string> LiStriOut)
     { LiStriOut = new List<string> { "Ciao", " Mondo!" }; }
   }
}
/*Output:
¡Hola Mundo!
Hello World!
Hallo Welt!
Ciao Mondo!
*/
  • AppendWorld: පිටපතක් StringListනම් LiStriසම්මත කර ඇත. ක්‍රමවේදය ආරම්භයේදී, මෙම පිටපතෙහි මුල් ලැයිස්තුව සඳහන් වන අතර එම නිසා මෙම ලැයිස්තුව වෙනස් කිරීමට භාවිතා කළ හැකිය. මුල් ලැයිස්තුවට බල නොපාන ක්‍රමවේදය තුළ LiStriතවත් List<string>වස්තුවක් පසුව සඳහන් කරයි.

  • HalloWelt: LiStriRefයනු දැනටමත් ආරම්භ කර ඇති අන්වර්ථයකි ListStringRef. සම්මත List<string>වස්තුව නව එකක් ආරම්භ කිරීම සඳහා භාවිතා කරයි, එබැවින් refඅවශ්‍ය විය.

  • CiaoMondo: LiStriOutඅන්වර්ථයක් වන ListStringOutඅතර එය ආරම්භ කළ යුතුය.

එබැවින්, සම්මත කරන ලද විචල්‍යය මඟින් සඳහන් කරන ලද වස්තුවක් ක්‍රමවේදයක් වෙනස් කරන්නේ නම්, සම්පාදකයා ඔබට භාවිතා කිරීමට ඉඩ නොදෙන අතර ඔබ එය භාවිතා outනොකළ යුත්තේ refඑය සම්පාදකයා නොව කේතය කියවන්නා ව්‍යාකූල කරන බැවිනි. මෙම ක්‍රමය මඟින් සම්මත කරන ලද තර්කය වෙනත් වස්තුවක් යොමු කරයි refනම්, දැනටමත් ආරම්භ කර ඇති outවස්තුවක් සඳහා සහ සම්මත කරන ලද තර්කය සඳහා නව වස්තුවක් ආරම්භ කළ යුතු ක්‍රම සඳහා භාවිතා කරන්න. ඒ විතරක් නෙවෙයි, refසහ outඑම වටේ සංචාරවල යෙදෙමින්.


2

ඒවා බොහෝ දුරට එක හා සමානයි - එකම වෙනස වන්නේ පිටත පරාමිතියක් ලෙස ඔබ සමත් විචල්‍යයක් ආරම්භ කිරීම අවශ්‍ය නොවන අතර ref පරාමිතිය භාවිතා කරන ක්‍රමය එය යම් දෙයකට සැකසිය යුතුය.

int x;    Foo(out x); // OK 
int y;    Foo(ref y); // Error

Ref පරාමිතීන් යනු වෙනස් කළ හැකි දත්ත සඳහා වන අතර, පිටත පරාමිතීන් යනු කිසියම් දෙයක් සඳහා ප්‍රතිලාභ අගය දැනටමත් භාවිතා කරන ශ්‍රිතය සඳහා අතිරේක ප්‍රතිදානයක් වන (උදා. Int.TryParse) දත්ත සඳහා ය.


2

Ref: ref යතුර භාවිතා කරන්නේ තර්කයක් යොමු කිරීමක් ලෙස ය. මෙයින් අදහස් කරන්නේ ක්‍රමයේ එම පරාමිතියේ අගය වෙනස් වූ විට එය ඇමතුම් ක්‍රමයෙන් පිළිබිඹු වන බවයි. Ref යතුරු පදයක් භාවිතයෙන් සම්මත කරන ලද තර්කයක්, එය හැඳින්වූ ක්‍රමයට යැවීමට පෙර ඇමතුම් ක්‍රමයේදී ආරම්භ කළ යුතුය.

පිටතට: ref යතුරුපදය වැනි තර්කයක් සම්මත කිරීම සඳහා පිටත යතුර භාවිතා කරයි, නමුත් තර්කය එයට කිසිදු වටිනාකමක් ලබා නොදී සම්මත කළ හැකිය. පිටත යතුරු පදයක් භාවිතයෙන් සම්මත කරන ලද තර්කයක් නැවත ඇමතුම් ක්‍රමයට පැමිණීමට පෙර එය හැඳින්වූ ක්‍රමයේදී ආරම්භ කළ යුතුය.

public class Example
{
 public static void Main() 
 {
 int val1 = 0; //must be initialized 
 int val2; //optional

 Example1(ref val1);
 Console.WriteLine(val1); 

 Example2(out val2);
 Console.WriteLine(val2); 
 }

 static void Example1(ref int value) 
 {
 value = 1;
 }
 static void Example2(out int value) 
 {
 value = 2; 
 }
}

/* Output     1     2     

ක්‍රමවේදය අධික ලෙස පැටවීමේදී නැවත යොමු වන්න

එකවර ක්‍රමවේදය පැටවීමේදී ref සහ out යන දෙකම භාවිතා කළ නොහැක. කෙසේ වෙතත්, ref සහ out ධාවනය වන වේලාවට වෙනස් ලෙස සලකනු ලැබේ, නමුත් ඒවා සම්පාදිත වේලාවට එක හා සමානව සලකනු ලැබේ (CLR, ref සහ out සඳහා IL නිර්මාණය කරන අතරම දෙක අතර වෙනස හඳුනා නොගනී).


1

පහත මම Ref සහ out යන දෙකම භාවිතා කරමින් උදාහරණයක් පෙන්වා ඇත . දැන්, ඔබ සියල්ලන්ම ref සහ out ගැන පැහැදිලි වනු ඇත.

පහත දැක්වෙන උදාහරණයේ මා අදහස් දක්වන විට // myRefObj = නව myClass {Name = "ref outside called !!"}; මාර්ගය, කියමින් දෝෂයක් ලැබෙනු ඇත "සභාවකට පවරා නැති දේශීය විචල්ය 'myRefObj' භාවිතය" , නමුත් කිසිදු එවැනි වරදක් තියෙනවා පිටතට .

Ref භාවිතා කළ යුතු ස්ථානය: අපි in පරාමිතියක් සහිත ක්‍රියා පටිපාටියක් අමතන විට එම ප්‍රොකට්ටුවේ ප්‍රතිදානය ගබඩා කිරීමට එකම පරාමිතිය භාවිතා කරනු ඇත.

පිටතට භාවිතා කළ යුතු ස්ථානය: අප විසින් පරාමිතියක් නොමැති ක්‍රියා පටිපාටියක් කැඳවන විට සහ එම පරාමිතියෙන් එම අගය ලබා ගැනීම සඳහා එකම පරාමිතිය භාවිතා කරනු ඇත. ප්‍රතිදානය ද සටහන් කරන්න

public partial class refAndOutUse : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        myClass myRefObj;
        myRefObj = new myClass { Name = "ref outside called!!  <br/>" };
        myRefFunction(ref myRefObj);
        Response.Write(myRefObj.Name); //ref inside function

        myClass myOutObj;
        myOutFunction(out myOutObj);
        Response.Write(myOutObj.Name); //out inside function
    }

    void myRefFunction(ref myClass refObj)
    {
        refObj.Name = "ref inside function <br/>";
        Response.Write(refObj.Name); //ref inside function
    }
    void myOutFunction(out myClass outObj)
    {
        outObj = new myClass { Name = "out inside function <br/>" }; 
        Response.Write(outObj.Name); //out inside function
    }
}

public class myClass
{
    public string Name { get; set; }
} 

1
 public static void Main(string[] args)
    {
        //int a=10;
        //change(ref a);
        //Console.WriteLine(a);
        // Console.Read();

        int b;
        change2(out b);
        Console.WriteLine(b);
        Console.Read();
    }
    // static void change(ref int a)
    //{
    //    a = 20;
    //}

     static void change2(out int b)
     {
         b = 20;
     }

ඔබට මෙම කේතය පරික්ෂා කළ හැකිය, ඔබ "ref" භාවිතා කරන විට එහි සම්පූර්ණ වෙනස විස්තර කරනු ඇත.

නමුත් ඔබ "පිටත" භාවිතා කරන විට එය කොන්දේසි දෙකෙහිම ක්‍රියාත්මක වේ.


0

පරාමිතියක් ලබා ගන්නා ක්‍රමයක දෘෂ්ටි කෝණයෙන්, සී # අතර වෙනස refහා නැවත පැමිණීමට පෙර outසෑම outපරාමිතියකටම ක්‍රම ලිවිය යුතු අතර, outපරාමිතියක් ලෙස සම්මත කිරීම හෝ එයට ලිවීම හැර වෙනත් පරාමිතියක් සමඟ කිසිවක් නොකළ යුතුය. , එය outවෙනත් ක්‍රමයකට පරාමිතියක් ලෙස සම්මත කරන තෙක් හෝ කෙලින්ම ලියන තුරු . වෙනත් සමහර භාෂාවන් එවැනි අවශ්‍යතා පනවන්නේ නැති බව සලකන්න. outපරාමිතියක් සමඟ C # හි ප්‍රකාශයට පත් කර ඇති අථත්‍ය හෝ අතුරුමුහුණත් ක්‍රමයක් වෙනත් භාෂාවකින් අභිබවා යා හැකි අතර එමඟින් එවැනි පරාමිතීන් සඳහා විශේෂ සීමාවන් පනවනු නොලැබේ.

අමතන්නාගේ දෘෂ්ටි කෝණයෙන්, C # බොහෝ අවස්ථාවන්හිදී outපරාමිතියක් සහිත ක්‍රමයක් ඇමතීමේදී සම්මත විචල්‍යය මුලින් කියවීමකින් තොරව ලිවීමට හේතු වනු ඇත. වෙනත් භාෂාවලින් ලියා ඇති ක්‍රම ඇමතීමේදී මෙම උපකල්පනය නිවැරදි නොවිය හැකිය. උදාහරණයක් වශයෙන්:

struct MyStruct
{
   ...
   myStruct(IDictionary<int, MyStruct> d)
   {
     d.TryGetValue(23, out this);
   }
}

C # හැර වෙනත් භාෂාවකින් ලියා myDictionaryඇති IDictionary<TKey,TValue>ක්‍රියාත්මක කිරීමක් හඳුනාගත හොත් MyStruct s = new MyStruct(myDictionary);, එය පැවරුමක් සේ පෙනුනද, එය ඉවත්ව යා හැකියs නවීකරණය නොකිරීමට ඉඩ ඇත.

C # හි ඇති ඒවා මෙන් නොව VB.NET හි ලියා ඇති ඉදිකිරීම්කරුවන්, කැඳවූ ක්‍රම මඟින් ඕනෑම outපරාමිතීන් වෙනස් කරනු ඇත්ද යන්න පිළිබඳව කිසිදු උපකල්පනයක් නොකරන අතර සියලු ක්ෂේත්‍රයන් කොන්දේසි විරහිතව ඉවත් කරයි. ඉහත දක්වා ඇති අමුතු හැසිරීම මුළුමනින්ම VB හෝ සම්පූර්ණයෙන්ම C # වලින් ලියා ඇති කේතයක් සමඟ සිදු නොවේ, නමුත් C # හි ලියා ඇති කේතය VB.NET හි ලියා ඇති ක්‍රමයක් ඇමතූ විට එය සිදුවිය හැකිය.


0

ඔබේ පරාමිතිය ref ලෙස සම්මත කිරීමට ඔබට අවශ්‍ය නම් පරාමිතිය ශ්‍රිතයට යැවීමට පෙර එය ආරම්භ කළ යුතුය. වෙනත් සම්පාදකයා විසින්ම දෝෂය පෙන්වනු ඇත. නමුත් පිටත පරාමිතියක නම් වස්තුව පරාමිතිය එය වෙත යැවීමට පෙර එය ආරම්භ කිරීම අවශ්‍ය නොවේ. ඇමතුම් ක්‍රමයේදී ඔබට වස්තුව ආරම්භ කළ හැකිය.


-3

ශ්‍රිතය තුළ සම්මත කර ඇති යොමු පරාමිතිය කෙලින්ම ක්‍රියාත්මක වන බව හොඳින් මතක තබා ගන්න.

උදාහරණයක් වශයෙන්,

    public class MyClass
    {
        public string Name { get; set; }
    }

    public void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog".
    }

    public void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

මෙය ලියන්නේ බල්ලා මිස කැට් නොවේ. එබැවින් ඔබ කෙලින්ම කිසියම් වස්තුවක් මත වැඩ කළ යුතුය.


6
මෙහි ඇති සෑම දෙයක්ම සෑහෙන්න සත්‍ය වුවත් එය ඇත්ත වශයෙන්ම අගය අනුව වෙනස හෝ යොමු කිරීම මගින් පැහැදිලි නොකරයි. යොමු සහ වටිනාකම / වෙනස් කළ නොහැකි වර්ග අතර වෙනස අඩක් එය පැහැදිලි කරයි.
කොන්රාඩ් ෆ්‍රික්ස්

ඔබට එම කේතය පූසා ලිවීමට අවශ්‍ය නම් කරුණාකර එම වස්තුව 'ref' යතුර සමඟ යවන්න: පොදු ස්ථිතික අවලංගු තීරුව (ref MyClass someObject), තීරුව (ref myObject);
ඩැනියෙල් බොටෙරෝ කොරියා

-4

මම මේ සම්බන්ධයෙන් එතරම් හොඳ නොවිය හැකි නමුත් නියත වශයෙන්ම නූල් (ඒවා තාක්‍ෂණිකව යොමු වර්ග වන අතර ගොඩවල් මත ජීවත් වුවද) වටිනාකමින් සම්මත වේ.

        string a = "Hello";

        string b = "goodbye";

        b = a; //attempt to make b point to a, won't work.

        a = "testing";

        Console.WriteLine(b); //this will produce "hello", NOT "testing"!!!!

මේ නිසා ඔබට ශ්‍රිතයේ විෂය පථයෙන් පිටත වෙනස්කම් සිදුවීමට අවශ්‍ය නම් ඔබට ref අවශ්‍ය වේ, ඔබ වෙනත් ආකාරයකින් යොමු කිරීමක් නොකරයි.

මා දන්නා තරමින් ඔබට අවශ්‍ය වන්නේ ව්‍යුහයන් / අගය වර්ග සහ නූල් සඳහා පමණි.

මම මෙහි සම්පූර්ණයෙන්ම වැරදියි, මම අලුත් ය.


5
ස්ටක් පිටාර ගැලීම වෙත සාදරයෙන් පිළිගනිමු, එඩ්වින්. මා දන්නා තරමින් වෙනත් ඕනෑම වස්තුවක් මෙන් නූල් යොමු කරනු ලැබේ. නූල් වෙනස් කළ නොහැකි වස්තූන් වන බැවින් ඔබ ව්‍යාකූල විය හැකිය, එබැවින් ඒවා යොමු කිරීම මගින් සම්මත වී ඇති බවක් නොපෙනේ. නූල් Capitalize()වල අන්තර්ගතය ලොකු අකුරු ලෙස වෙනස් කරන ක්‍රමයක් ඇතැයි සිතන්න . එවිට ඔබට ඔබේ මාර්ගය වෙනුවට නම් a = "testing";සමග a.Capitalize();, ඉන්පසු ඔබේ ප්රතිදානය "HELLO", නැත "හෙලෝ" වනු ඇත. වෙනස් කළ නොහැකි වර්ගවල එක් වාසියක් නම්, ඔබට යොමු කිරීම් හරහා ගමන් කළ හැකි අතර අනෙක් කේතවල වටිනාකම වෙනස් වීම ගැන කරදර නොවන්න.
දොන් කිර්ක්බි

2
එක් වර්ගයකට නිරාවරණය කළ හැකි මූලික අර්ථකථන වර්ග තුනක් ඇත: විකෘති යොමු අර්ථ නිරූපණය, විකෘති අගය අර්ථ නිරූපණය සහ වෙනස් කළ නොහැකි අර්ථ නිරූපණය. ක්ෂේත්‍ර හෝ දේපල m ඇති T වර්ගයේ x සහ y විචල්‍යයන් සලකා බලන්න, x යන්න y ට පිටපත් කර ඇතැයි සිතමු. T ට යොමු අර්ථකථන තිබේ නම්, xm හි වෙනස්කම් ym විසින් නිරීක්ෂණය කරනු ලැබේ. T ට අගය අර්ථකථන තිබේ නම්, යමෙකුට ym ට බලපෑමක් නොකර xm වෙනස් කළ හැකිය. වෙනස් කළ නොහැකි අර්ථකථන යොමු හෝ වටිනාකම් වස්තු මගින් අනුකරණය කළ හැකිය. නූල් යනු වෙනස් කළ නොහැකි යොමු වස්තු වේ.
සුපර් කැට්
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.