වස්තුවක් සම්මත කිරීමට අවශ්ය තැන මම ශ්රිතයක් නිර්මාණය කරමි. අතර ඇති වෙනස කුමක්ද:
public void myFunction(ref MyClass someClass)
සහ
public void myFunction(out MyClass someClass)
මා භාවිතා කළ යුත්තේ කුමක්ද සහ ඇයි?
වස්තුවක් සම්මත කිරීමට අවශ්ය තැන මම ශ්රිතයක් නිර්මාණය කරමි. අතර ඇති වෙනස කුමක්ද:
public void myFunction(ref MyClass someClass)
සහ
public void myFunction(out MyClass someClass)
මා භාවිතා කළ යුත්තේ කුමක්ද සහ ඇයි?
Answers:
ref
ශ්රිතයට ඇතුළු වීමට පෙර වස්තුව ආරම්භ කර ඇති out
බව සම්පාදකයාට පවසන අතර, ශ්රිතය තුළ වස්තුව ආරම්භ කරන බව සම්පාදකයාට පවසයි.
එබැවින් ref
දෙයාකාරයක් තිබියදීත්, out
පිටත පමණි.
මෙම ref
විකරණකාරකය මාධ්යයන්:
මෙම out
විකරණකාරකය මාධ්යයන්:
out
, එය, ඒ ක්රමය මගින් නියම කර ඇති ක්රමය නම් පෙර එය ආරම්භනය කර තිබේ නම්, තියෙන්නේ කලින් එය, සියලු දී කියවිය හැකි ක්රමය තුළ? මා අදහස් කළේ, කැඳවුම් ක්රමයට තර්කයක් ලෙස ඇමතුම් ක්රමය එයට ලබා දුන් දේ කියවිය හැකිද?
ටීපීඑස් වාර්තා පිළිබඳ සංදේශය ගැන ඩොම් පීටර්ගේ කුටියේ පෙන්වන බව කියමු.
ඩොම් ref තර්කයක් නම්, ඔහුට සංදේශයේ මුද්රිත පිටපතක් තිබේ.
ඩොම් බාහිර තර්කයක් නම්, ඔහු සමඟ රැගෙන යාම සඳහා ඔහු විසින් සංදේශයේ නව පිටපතක් මුද්රණය කරනු ඇත.
පැහැදිලි කිරීමකදී මම මගේ අත උත්සාහ කරමි:
මම හිතන්නේ අපි තේරුම් ගත්තා වටිනාකම් වර්ග නිවැරදිව ක්රියා කරන්නේ කෙසේද? අගය වර්ග (int, long, struct ආදිය). Ref විධානයක් නොමැතිව ඔබ ඒවා ශ්රිතයකට යවන විට එය දත්ත පිටපත් කරයි . ශ්රිතයේ එම දත්ත සඳහා ඔබ කරන ඕනෑම දෙයක් බලපාන්නේ පිටපතට මිස මුල් පිටපතට නොවේ. Ref විධානය මඟින් ACTUAL දත්ත යවන අතර ඕනෑම වෙනස්කමක් ශ්රිතයෙන් පිටත දත්ත වලට බලපායි.
අවුල් සහගත කොටස වෙත යොමු වන්න, යොමු වර්ග:
යොමු වර්ගයක් නිර්මාණය කිරීමට ඉඩ දෙමු:
List<string> someobject = new List<string>()
ඔබ යම්කිසි දෙයක් අලුත් කළ විට , කොටස් දෙකක් සාදනු ලැබේ:
දැන් ඔබ කිසියම් වස්තුවක් යොමු නොකර ක්රමයකට යවන විට එය යොමු දර්ශකය පිටපත් කරයි , දත්ත නොවේ. එබැවින් ඔබට දැන් මෙය තිබේ:
(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
හා out
පරාමිතීන්.
out
මූල පදය සඳහා ඔබට එයම පැහැදිලි කළ හැකිද?
out
ඔබේ අවශ්යතාවයන් සඳහා ප්රමාණවත් වන ඕනෑම තැනක ඔබ මනාපයෙන් භාවිතා කළ යුතුය .
C # හි, ක්රමයකට ආපසු ලබා දිය හැක්කේ එක් අගයක් පමණි. ඔබ එකකට වඩා වැඩි වටිනාකමක් ලබා දීමට කැමති නම්, ඔබට පිටත යතුරු පදය භාවිතා කළ හැකිය. පිටත විකරණකාරකය ආපසු-යොමු-යොමු ලෙස ආපසු එයි. සරලම පිළිතුර නම් ක්රමයෙන් වටිනාකම ලබා ගැනීම සඳහා “පිටතට” යන පදය භාවිතා කිරීමයි.
C # හි, ඔබ ක්රම පරාමිතියට තර්කයක් ලෙස int, float, double ආදී අගයන් වර්ගයක් සම්මත කළ විට එය අගය මගින් සම්මත වේ. එමනිසා, ඔබ පරාමිති අගය වෙනස් කරන්නේ නම්, එය ක්රම ඇමතුමේ තර්කයට බලපාන්නේ නැත. නමුත් ඔබ පරාමිතිය “ref” යතුරු පදයෙන් සලකුණු කළහොත් එය සත්ය විචල්යයෙන් පිළිබිඹු වේ.
බල්ලා දිගු කිරීම, බළලා උදාහරණය. 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;
}
ඔබ යොමු වර්ගයක (පංතියක) පසු වන බැවින් භාවිතයේ අවශ්යතාවයක් නොමැත, 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
ඔබේ ක්රමය තුළ ඇති වස්තුව වෙනස් කිරීමට අවශ්ය නම් ඔබ භාවිතා කළ යුතු නොවේ .
someObject = null
කිරීමට Bar
අවසානයට එක් කරන්න. ඔබගේ කේතය හොඳින් ක්රියාත්මක Bar
වන්නේ නිදසුන පිළිබඳ සඳහනක් පමණක් අවලංගු කර ඇති බැවිනි. දැන් වෙනස් Bar
කර Bar(ref MyClass someObject)
නැවත ක්රියාත්මක කරන්න - ඔබට උදාහරණය පිළිබඳ සඳහනක් ද අවලංගු කර ඇති NullReferenceException
නිසා ඔබට එය ලැබෙනු Foo
ඇත.
ref
out
පහත සඳහන් වෙනස්කම් හැර ඒ හා සමානව හැසිරෙන්න.
ref
භාවිතයට පෙර විචල්යය ආරම්භ කළ යුතුය. out
පැවරුමකින් තොරව විචල්යය භාවිතා කළ හැකියout
පරාමිතිය එය භාවිතා කරන ශ්රිතය මගින් නියම නොකළ අගයක් ලෙස සැලකිය යුතුය. එබැවින්, අපට out
ඇමතුම් කේතයේ ආරම්භක පරාමිතිය භාවිතා කළ හැකිය , නමුත් ශ්රිතය ක්රියාත්මක වන විට අගය නැති වේ.ආදර්ශයෙන් ඉගෙන ගන්නා අයට (මා වැනි) ඇන්තනි කොලෙසොව් පවසන දේ මෙන්න .
කාරණය නිදර්ශනය කිරීම සඳහා මම ref, out, සහ වෙනත් උදාහරණ කිහිපයක් නිර්මාණය කර ඇත්තෙමි. මම හොඳම භාවිතයන් ආවරණය නොකරමි, වෙනස්කම් තේරුම් ගැනීමට උදාහරණ පමණි.
"බේකර්"
එයට හේතුව පළමුවැන්න ඔබේ නූල් යොමුව “බේකර්” වෙත යොමු කිරීමයි. ඔබ එය ref යතුරුපදය හරහා සම්මත කළ නිසා (=> නූලකට යොමු කිරීමකට යොමු කිරීම) යොමු කිරීම වෙනස් කළ හැකිය. දෙවන ඇමතුමට නූලට යොමු කිරීමේ පිටපතක් ලැබේ.
නූල් මුලින් යම් ආකාරයක විශේෂ පෙනුමක්. නමුත් නූල් යනු යොමු පන්තියක් පමණක් වන අතර ඔබ අර්ථ දක්වන්නේ නම්
string s = "Able";
s යනු “Able” පා text ය අඩංගු නූල් පන්තියකට යොමු කිරීමකි! එකම විචල්යයට තවත් පැවරුමක්
s = "Baker";
මුල් නූල වෙනස් නොකරන නමුත් නව අවස්ථාවක් නිර්මාණය කර එම අවස්ථාව වෙත යොමු වීමට ඉඩ දෙන්න!
පහත දැක්වෙන කුඩා කේත උදාහරණය සමඟ ඔබට එය උත්සාහ කළ හැකිය:
string s = "Able";
string s2 = s;
s = "Baker";
Console.WriteLine(s2);
ඔබ බලාපොරොත්තු වන්නේ මොනවද? ඔබට ලැබෙන දෙය තවමත් "හැකියාව" වන්නේ ඔබ s හි මුල් උදාහරණයට යොමු කරන අතරම වෙනත් අවස්ථාවකට යොමු කිරීම ය.
සංස්කරණය කරන්න: නූල් ද වෙනස් කළ නොහැකි ය, එයින් අදහස් කරන්නේ දැනට පවතින නූල් නිදසුනක් වෙනස් කරන ක්රමවේදයක් හෝ දේපලක් නොමැති බවයි (ඔබට ලේඛනයේ එකක් සොයා ගැනීමට උත්සාහ කළ හැකි නමුත් ඔබට වරල් කිසිවක් නොලැබේ :-)). සියලුම නූල් හැසිරවීමේ ක්රම නව සංගීත අවස්ථාවක් ලබා දෙයි! (StringBuilder පන්තිය භාවිතා කරන විට ඔබට බොහෝ විට වඩා හොඳ කාර්ය සාධනයක් ලැබෙන්නේ එබැවිනි)
ref යන්නෙන් අදහස් වන්නේ ref පරාමිතියේ අගය දැනටමත් සකසා ඇති බැවින් ක්රමයට එය කියවා වෙනස් කළ හැකිය. පරාමිතිකයේ අගය ආරම්භ කිරීම සඳහා අමතන්නා වගකිව යුතු යැයි පැවසීම ref යතුර භාවිතා කිරීම සමාන වේ.
අවුට් සම්පාදකයාට පවසන්නේ වස්තුව ආරම්භ කිරීම ශ්රිතයේ වගකීම බවයි, ශ්රිතය පිටත පරාමිතියට පැවරිය යුතුය. එය නියම නොකල ලෙස තැබීමට අවසර නැත.
පිටතට: ශ්රිතයකින් එක් අගයක් පමණක් ලබා දීම සඳහා ආපසු ප්රකාශයක් භාවිතා කළ හැකිය. කෙසේ වෙතත්, ප්රතිදාන පරාමිතීන් භාවිතා කිරීමෙන් ඔබට ශ්රිතයකින් අගයන් දෙකක් ආපසු ලබා දිය හැකිය. නිමැවුම් පරාමිතීන් යොමු පරාමිතීන් හා සමාන වේ, ඒවා දත්ත වලට වඩා ක්රමයෙන් පිටතට මාරු කිරීම හැර.
පහත උදාහරණයෙන් මෙය පැහැදිලි වේ:
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();
}
}
}
සංක්ෂිප්ත පිළිතුරක් සොයන අයට.
දෙකම
ref
සහout
මූල පද පසුකර යාමට භාවිතා කරයිreference
.
ක විචල්ය
ref
ඉඟි පද අගය තිබිය යුතුය හෝ වස්තුවක් හෝ යොමු කළ යුතුයnull
පෙර එහි සම්මත.
මෙන් නොව
ref
, ක විචල්යout
ඉඟි පද අගය තිබිය යුතුය හෝ වස්තුවක් හෝ යොමු කළ යුතුයnull
පසු එහි සම්මත මෙන්ම අගය හෝ වස්තුවක් වෙත යොමු කිරීමට කිසිදු අවශ්යතාවයක් පෙර ගමන්.
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);
out double Half_nbr
.
කර්තෘ කාලය:
(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) සමඟ ගොඩගැසී ඇති වස්තුවක් නිර්මාණය කිරීම සහ එහි ආරම්භක ලිපිනය තර්ක විචල්යය තුළ ගබඩා කිරීම. ආරම්භ නොකළ දෝෂයක් විසි නොවන අතර කලින් ගබඩා කර තිබූ කිසිදු සඳහනක් නැති වී යයි.
හොඳින් පන්තියේ විවිධ උදාහරණයක් කිරීමට නැවත පැවරීම තව කෙනෙකුගේ විචල්ය කිරීමට ඔබට ඉඩ තරම්, ආදිය බහු වටිනාකම් නැවත භාවිතා ref
හෝ out
වෙන කෙනෙක් ඔබ ඔවුන්ගෙන් අවශ්ය දේ දැන ගැනීමට ඉඩ සලස්වන සහ ඔබ ඔවුන් සපයන විචල්ය සමග අදහස්
ඔබට අවශ්ය නැත, ref
නැතහොත් out
ඔබ කිරීමට යන්නේ තර්කයේ සම්මත කර ඇති උදාහරණය තුළ ඇති දේවල් වෙනස් කිරීම පමණි .MyClass
someClass
someClass.Message = "Hello World"
ඔබ භාවිතා යන්න ref
, out
හෝ කිසිවක්someClass = new MyClass()
ඇතුළත ලිවීම ක්රමයේ විෂය පථයට පමණක් myFunction(someClass)
පෙනෙන වස්තුව මාරු කරයි . ඇමතුම් ක්රමය තවමත් එය නිර්මාණය කර ඔබේ ක්රමයට ලබා දුන් මුල් අවස්ථාව ගැන දනීsomeClass
myFunction
MyClass
ඔබට අවශ්ය නම් ref
හෝ out
ඔබ someClass
නව වස්තුවක් සඳහා හුවමාරු කර ගැනීමට අදහස් කරන්නේ නම් සහ ඔබේ වෙනස දැකීමට ඇමතුම් ක්රමයට අවශ්ය නම්
someClass = new MyClass()
ඇතුළත ලිවීමෙන් myFunction(out someClass)
හැඳින්වූ ක්රමය මඟින් දකින වස්තුව වෙනස් වේmyFunction
ඔවුන්ගේ දත්ත සමඟ ඔබ කුමක් කරන්නදැයි ඔවුන්ට දැන ගැනීමට අවශ්යය. ඔබ මිලියන ගණනක් සංවර්ධකයින් භාවිතා කරන පුස්තකාලයක් ලියන බව සිතන්න. ඔවුන් ඔබේ ක්රමවේදයන් අමතන විට ඔවුන්ගේ විචල්යයන් සමඟ ඔබ කුමක් කරන්නදැයි ඔවුන් දැන ගැනීමට ඔබට අවශ්යය
භාවිතා ref
කිරීම ප්රකාශයක් කරයි "ඔබ මගේ ක්රමය අමතන විට යම් අගයකට පවරා ඇති විචල්යයක් පසු කරන්න. මගේ ක්රමවේදය තුළ එය වෙනත් දෙයක් සඳහා සම්පූර්ණයෙන්ම වෙනස් කළ හැකි බව මතක තබා ගන්න. ඔබේ විචල්යය පැරණි වස්තුව වෙත යොමු වනු ඇතැයි අපේක්ෂා නොකරන්න මම ඉවර වුනාම "
භාවිතා out
කිරීම "මගේ ක්රමයට ස්ථාන දරණ විචල්යයක් ලබා දෙන්න. එහි වටිනාකමක් තිබේද නැද්ද යන්න ගැටළුවක් නොවේ; එය නව අගයකට පැවරීමට සම්පාදකයා මට බල කරයි. ඔබේ වස්තුව පෙන්වා දුන් වස්තුව මම සහතික කරමි. ඔබ මගේ ක්රමයට කතා කිරීමට පෙර විචල්යය, මා අවසන් වන විට වෙනස් වේ
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 මගින් ප්රතිස්ථාපනය වේ
බොහෝ විශිෂ්ට පැහැදිලි කිරීම් නිදර්ශනය කිරීම සඳහා, මම පහත කොන්සෝල යෙදුම සංවර්ධනය කළෙමි:
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
එම වටේ සංචාරවල යෙදෙමින්.
ඒවා බොහෝ දුරට එක හා සමානයි - එකම වෙනස වන්නේ පිටත පරාමිතියක් ලෙස ඔබ සමත් විචල්යයක් ආරම්භ කිරීම අවශ්ය නොවන අතර ref පරාමිතිය භාවිතා කරන ක්රමය එය යම් දෙයකට සැකසිය යුතුය.
int x; Foo(out x); // OK
int y; Foo(ref y); // Error
Ref පරාමිතීන් යනු වෙනස් කළ හැකි දත්ත සඳහා වන අතර, පිටත පරාමිතීන් යනු කිසියම් දෙයක් සඳහා ප්රතිලාභ අගය දැනටමත් භාවිතා කරන ශ්රිතය සඳහා අතිරේක ප්රතිදානයක් වන (උදා. Int.TryParse) දත්ත සඳහා ය.
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 නිර්මාණය කරන අතරම දෙක අතර වෙනස හඳුනා නොගනී).
පහත මම 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; }
}
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" භාවිතා කරන විට එහි සම්පූර්ණ වෙනස විස්තර කරනු ඇත.
නමුත් ඔබ "පිටත" භාවිතා කරන විට එය කොන්දේසි දෙකෙහිම ක්රියාත්මක වේ.
පරාමිතියක් ලබා ගන්නා ක්රමයක දෘෂ්ටි කෝණයෙන්, සී # අතර වෙනස 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 හි ලියා ඇති ක්රමයක් ඇමතූ විට එය සිදුවිය හැකිය.
ඔබේ පරාමිතිය ref ලෙස සම්මත කිරීමට ඔබට අවශ්ය නම් පරාමිතිය ශ්රිතයට යැවීමට පෙර එය ආරම්භ කළ යුතුය. වෙනත් සම්පාදකයා විසින්ම දෝෂය පෙන්වනු ඇත. නමුත් පිටත පරාමිතියක නම් වස්තුව පරාමිතිය එය වෙත යැවීමට පෙර එය ආරම්භ කිරීම අවශ්ය නොවේ. ඇමතුම් ක්රමයේදී ඔබට වස්තුව ආරම්භ කළ හැකිය.
ශ්රිතය තුළ සම්මත කර ඇති යොමු පරාමිතිය කෙලින්ම ක්රියාත්මක වන බව හොඳින් මතක තබා ගන්න.
උදාහරණයක් වශයෙන්,
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;
}
මෙය ලියන්නේ බල්ලා මිස කැට් නොවේ. එබැවින් ඔබ කෙලින්ම කිසියම් වස්තුවක් මත වැඩ කළ යුතුය.
මම මේ සම්බන්ධයෙන් එතරම් හොඳ නොවිය හැකි නමුත් නියත වශයෙන්ම නූල් (ඒවා තාක්ෂණිකව යොමු වර්ග වන අතර ගොඩවල් මත ජීවත් වුවද) වටිනාකමින් සම්මත වේ.
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 අවශ්ය වේ, ඔබ වෙනත් ආකාරයකින් යොමු කිරීමක් නොකරයි.
මා දන්නා තරමින් ඔබට අවශ්ය වන්නේ ව්යුහයන් / අගය වර්ග සහ නූල් සඳහා පමණි.
මම මෙහි සම්පූර්ණයෙන්ම වැරදියි, මම අලුත් ය.
Capitalize()
වල අන්තර්ගතය ලොකු අකුරු ලෙස වෙනස් කරන ක්රමයක් ඇතැයි සිතන්න . එවිට ඔබට ඔබේ මාර්ගය වෙනුවට නම් a = "testing";
සමග a.Capitalize();
, ඉන්පසු ඔබේ ප්රතිදානය "HELLO", නැත "හෙලෝ" වනු ඇත. වෙනස් කළ නොහැකි වර්ගවල එක් වාසියක් නම්, ඔබට යොමු කිරීම් හරහා ගමන් කළ හැකි අතර අනෙක් කේතවල වටිනාකම වෙනස් වීම ගැන කරදර නොවන්න.
MyClass
විය හැකි බවටclass
වර්ගය, එනම්, සමුද්දේශ වර්ගය. එවැනි අවස්ථාවකදී, ඔබ පසු කරන වස්තුවmyFunction
කිසිදුref
/out
යතුරු පදයකින් තොරව වෙනස් කළ හැකිය . එකම වස්තුවකට යොමු වන නව යොමු කිරීමක්myFunction
ලැබෙනු ඇති අතර, එම වස්තුවට අවශ්ය ප්රමාණයට වෙනස් කළ හැකිය. මෙම වෙනස ඉඟි පද කරන්න වනු ඇත, එසේ නම් ඔහු ලැබුණු එකම එකම වස්තුව සඳහන්. එය වැදගත් වන්නේ වෙනත් වස්තුවකට යොමු කිරීම සඳහා යොමු කිරීම වෙනස් කළහොත් පමණි .ref
myFunction
myFunction