වර්ගය පරීක්ෂා කිරීම: typeof, GetType, හෝ?


1524

බොහෝ අය පහත කේතය භාවිතා කරන බව මම දැක ඇත්තෙමි:

Type t = typeof(obj1);
if (t == typeof(int))
    // Some code here

නමුත් මම දන්නවා ඔබටත් මෙය කළ හැකි බව:

if (obj1.GetType() == typeof(int))
    // Some code here

හෝ මෙය:

if (obj1 is int)
    // Some code here

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


28
අමතක කරන්න asඑපා!
RCIX

84
asඇත්ත වශයෙන්ම ටයිප් පරීක්‍ෂා කිරීමක් නොවේ ...
ජේසන්

49
asසෑම වර්ගයකම තරමටම වර්ග පරීක්ෂා කිරීමේ ආකාරයකි is! එය isතිරය ​​පිටුපස effectively ලදායී ලෙස භාවිතා කරන අතර එම්එස්ඩීඑන් හි සෑම තැනකම එය කේත පිරිසිදුකමට එදිරිව කේත පිරිසිදු isකරයි. isපළමුව පරීක්ෂා කිරීම වෙනුවට, asභාවිතයට සුදානම් වන ටයිප් කළ විචල්‍යයක් ස්ථාපිත කිරීම සඳහා වූ ඇමතුමක් : එය ශුන්‍ය නම්, නිසි පරිදි ප්‍රතිචාර දක්වන්න; එසේ නොමැතිනම් ඉදිරියට යන්න. නිසැකවම මා දුටු හා භාවිතා කළ දෙයක්.
සැකෝන්

16
ඔබේ නඩුව සඳහා එහි අර්ථකථන ක්‍රියා උපකල්පනය කරමින් as/ is( stackoverflow.com/a/27813381/477420 හි ආවරණය කර ඇති ) සඳහා සැලකිය යුතු කාර්යසාධන වෙනසක් ඇත .
ඇලෙක්සි ලෙවෙන්කොව්

am සමුසුරින් එය පරාවර්තනය "භාවිතා" නොකරයි. මෙම GetTypeඔබ මෙකෙදි ක්රමය වන්නේ System.Reflection.Assemblyමෙහි සම්පූර්ණයෙන්ම වෙනස් ක්රමයක් හා අනදාල -.
කිර්ක් වොල්

Answers:


1867

සියල්ල වෙනස් ය.

  • typeof වර්ග නාමයක් ගනී (ඔබ සම්පාදනය කරන වේලාවේදී සඳහන් කරයි).
  • GetType උදාහරණයක ධාවන කාල වර්ගය ලබා ගනී.
  • is උරුමය ගසෙහි නිදසුනක් තිබේ නම් එය සත්‍ය වේ.

උදාහරණයක්

class Animal { } 
class Dog : Animal { }

void PrintTypes(Animal a) { 
    Console.WriteLine(a.GetType() == typeof(Animal)); // false 
    Console.WriteLine(a is Animal);                   // true 
    Console.WriteLine(a.GetType() == typeof(Dog));    // true
    Console.WriteLine(a is Dog);                      // true 
}

Dog spot = new Dog(); 
PrintTypes(spot);

කුමක් ගැනද typeof(T)? එය සම්පාදනය කරන වේලාවේදී ද විසඳා තිබේද?

ඔව්. T යනු සැමවිටම ප්‍රකාශනයේ වර්ගයයි. මතක තබා ගන්න, සාමාන්‍ය ක්‍රමයක් යනු මූලික වශයෙන් සුදුසු වර්ගයක් සහිත ක්‍රම සමූහයකි. උදාහරණයක්:

string Foo<T>(T parameter) { return typeof(T).Name; }

Animal probably_a_dog = new Dog();
Dog    definitely_a_dog = new Dog();

Foo(probably_a_dog); // this calls Foo<Animal> and returns "Animal"
Foo<Animal>(probably_a_dog); // this is exactly the same as above
Foo<Dog>(probably_a_dog); // !!! This will not compile. The parameter expects a Dog, you cannot pass in an Animal.

Foo(definitely_a_dog); // this calls Foo<Dog> and returns "Dog"
Foo<Dog>(definitely_a_dog); // this is exactly the same as above.
Foo<Animal>(definitely_a_dog); // this calls Foo<Animal> and returns "Animal". 
Foo((Animal)definitely_a_dog); // this does the same as above, returns "Animal"

29
අහ්, මට කාර් වෙතින් ව්‍යුත්පන්න වූ ෆෝඩ් පංතියක් සහ ෆෝඩ් නිදසුනක් තිබේ නම්, එම අවස්ථාවෙහිදී “කාර්” යන්න පරීක්ෂා කිරීම සත්‍ය වේ. තේරුමක් ඇති!
jasonh

2
පැහැදිලි කිරීම සඳහා, මම ඒ ගැන දැන සිටියෙමි, නමුත් ඔබ කේත නියැදියක් එක් කිරීමට පෙර අදහස් දැක්වුවෙමි. ඔබගේ දැනටමත් විශිෂ්ට පිළිතුරට සරල ඉංග්‍රීසි පැහැදිලි කිරීමක් එක් කිරීමට මට අවශ්‍ය විය.
jasonh

12
H ෂිමී ටයිප් ඕෆ් සම්පාදනය කරන වේලාවේදී සහ ගෙටයිප් () ධාවන වේලාවේදී ඇගයීමට ලක් කරන්නේ නම්, එවිට GetType () සුළු කාර්ය සාධනයක් ලබා ඇති බව හැඟේ
සෙඩ්රික් මාමෝ

නව බල්ලා () ගැන කුමක් කිව හැකිද? GetType () යනු සත්ව හෝ යතුරු ලියනය (බල්ලා) සත්ව වේ, එය අනතුරු ඇඟවීමක් මිස දෝෂයක් නොවේද?
Prerak K

7
@PrerakK new Dog().GetType() is Animalසිට බොරු (සහ ඔබගේ අනෙකුත් අනුවාදය මෙන්ම) නැවත .GetType()ප්රතිලාභ වර්ගය වස්තුවක් Type, සහ Typeකිසිවක් නිසා නොවේ Animal.
මාර්ටන්

197

සම්පාදනය කරන වේලාවේදීtypeof වර්ගය ලබා ගැනීමට ඔබට අවශ්‍ය විට භාවිතා කරන්න . ක්‍රියාත්මක කිරීමේ වේලාවේදී වර්ගය ලබා ගැනීමට ඔබට අවශ්‍ය විට භාවිතා කරන්න . වාත්තු කිරීමක් ලෙස භාවිතා කිරීමට ඕනෑම අවස්ථාවක් කලාතුරකින් ඇති අතර බොහෝ විට ඔබ කෙසේ හෝ විචල්‍යය වාත්තු කිරීම අවසන් කරයි.GetTypeis

ඔබ නොසැලකූ සිව්වන විකල්පයක් ඇත (විශේෂයෙන් ඔබ සොයා ගන්නා වර්ගයට ඔබ වස්තුවක් දැමීමට යන්නේ නම්); එනම් භාවිතා කිරීමයි as.

Foo foo = obj as Foo;

if (foo != null)
    // your code here

මෙය භාවිතා කරන්නේ එක් වාත්තු කිරීමක් පමණක් වන අතර මෙම ප්‍රවේශය:

if (obj is Foo)
    Foo foo = (Foo)obj;

දෙකක් අවශ්‍යයි .

යාවත්කාලීන කිරීම (2020 ජනවාරි):

  • C # 7+ වන විට , ඔබට දැන් පේළිගත කළ හැකිය, එබැවින් 'is' ප්‍රවේශය දැන් එක් කාස්ට් එකක ද කළ හැකිය.

උදාහරණයක්:

if(obj is Foo newLocalFoo)
{
    // For example, you can now reference 'newLocalFoo' in this local scope
    Console.WriteLine(newLocalFoo);
}

4
.NET 4 හි වෙනස්වීම් සමඟ isතවමත් වාත්තු කිරීමක් සිදු වේද?
ahsteele

6
මෙම පිළිතුර නිවැරදි ද? ඔබට ඇත්ත වශයෙන්ම නිදසුනක් ටයිප් ඔෆ් () වෙත යැවිය හැකි බව ඇත්තද? මගේ අත්දැකීම් නැත. නමුත් මම සිතන්නේ සාමාන්‍යයෙන් සත්‍යයක් සිදුවීම පරීක්ෂා කිරීම ධාවන වේලාවේදී සිදුවිය යුතු අතර පංතියක් පරික්ෂා කිරීම සම්පාදනය කරන වේලාවේදී කළ හැකි බවය.
ජෝන් කුම්බ්ස්

4
on ජෝන් (ඔබේ q ට වසර 4 කට පසු), නැත, ඔබට නිදසුනක් ඇතුල් කළ නොහැක typeof(), මෙම පිළිතුර ඔබට හැකි යැයි යෝජනා නොකරයි. ඔබ ඒ වෙනුවට වර්ගය පසු කරයි, එනම්, typeof(string)ක්‍රියා කරයි, typeof("foo")නැත.
ආබෙල්

isඅයිඑල් හි විශේෂ මෙහෙයුමක් ලෙස මම විශ්වාස නොකරමි .
abatishchev

3
අපට දැන් කළ හැකියif (obj is Foo foo) { /* use foo here */ }
අයිවන් ගාර්ෂියා ටොපෙට්

74

1.

Type t = typeof(obj1);
if (t == typeof(int))

මෙය නීති විරෝධී ය, මන්ද typeofක්‍රියා කරන්නේ විචල්‍යයන් මත නොව වර්ග මත පමණි. මම හිතන්නේ obj1 විචල්යයක්. ඉතින්, මේ ආකාරයෙන් typeofස්ථිතික වන අතර, එහි ක්‍රියාකාරීත්වය ධාවන කාලය වෙනුවට සම්පාදනය කරන වේලාවේදී සිදු කරයි.

2.

if (obj1.GetType() == typeof(int))

මේ trueනම් obj1හරියටම ආකාරයේ වන int. obj1ව්‍යුත්පන්න නම් int, if කොන්දේසිය වනු ඇත false.

3.

if (obj1 is int)

මේ trueනම් obj1යනු int, හෝ එය නමින් පන්ති උපද්දවා නම් int, හෝ එය හැඳින්වූයේ අතුරු මුහුණතක් ක්රියාත්මක නම් int.


1 ගැන සිතමින්, ඔබ හරි. තවමත්, මම එය මෙහි කේත සාම්පල කිහිපයකින් දැක ඇත්තෙමි. එය වර්ගය t = obj1.GetType () විය යුතුය;
jasonh

4
ඔව්, මම හිතන්නේ එහෙමයි. "typeof (obj1)" මම එය උත්සාහ කරන විට සම්පාදනය නොකරයි.
ස්කොට් ලැන්ග්හැම්

4
System.Int32 හෝ C #
reggaeguitar

typeof (typeof (system.int32)) යනු කුමක්දැයි ඔබට පැවසිය හැකිද
සනා

1
Ana සානා, ඇයි ඔබ එය උත්සාහ නොකරන්නේ :) System.Type වර්ගය නියෝජනය කරන System.Type හි උදාහරණයක් ඔබ නැවත ලබා ගත්තද මම සිතමි. Typeof
ස්කොට් ලැන්ග්හැම්

53
Type t = typeof(obj1);
if (t == typeof(int))
    // Some code here

මෙය දෝෂයකි. C # හි යතුරු ලියන ක්‍රියාකරුට ගත හැක්කේ වස්තු නොව වර්ග නාම පමණි.

if (obj1.GetType() == typeof(int))
    // Some code here

මෙය ක්‍රියාත්මක වනු ඇත, නමුත් සමහර විට ඔබ බලාපොරොත්තු වන පරිදි නොවේ. වටිනාකම් වර්ග සඳහා, ඔබ මෙහි පෙන්වා ඇති පරිදි, එය පිළිගත හැකි නමුත් යොමු වර්ග සඳහා, එය සත්‍ය බවට පත්වන්නේ එම වර්ගය හරියටම එකම වර්ගයේ නම් මිස උරුම ධූරාවලියේ වෙනත් දෙයක් නොවේ. උදාහරණයක් වශයෙන්:

class Animal{}
class Dog : Animal{}

static void Foo(){
    object o = new Dog();

    if(o.GetType() == typeof(Animal))
        Console.WriteLine("o is an animal");
    Console.WriteLine("o is something else");
}

මෙම මුද්රණය කරන "o is something else"වර්ගය නිසා oDog, නැත Animal. කෙසේ වෙතත්, ඔබ පන්තියේ IsAssignableFromක්‍රමය භාවිතා කරන්නේ නම් ඔබට මෙම කාර්යය කළ හැකිය Type.

if(typeof(Animal).IsAssignableFrom(o.GetType())) // note use of tested type
    Console.WriteLine("o is an animal");

මෙම තාක්ෂණය තවමත් විශාල ගැටලුවක්ව පවතී. ඔබගේ විචල්‍යය ශුන්‍ය නම්, ඇමතුම GetType()NullReferenceException එකක් දමනු ඇත. එබැවින් එය නිවැරදිව ක්‍රියාත්මක කිරීම සඳහා, ඔබ කරන්නේ:

if(o != null && typeof(Animal).IsAssignableFrom(o.GetType()))
    Console.WriteLine("o is an animal");

මේ සමඟ, ඔබට යතුරුපදයේ සමාන හැසිරීමක් ඇත is. එබැවින්, ඔබට අවශ්‍ය හැසිරීම මෙය නම්, ඔබ isකියවිය යුතු හා වඩා කාර්යක්ෂම වන යතුරු පදය භාවිතා කළ යුතුය .

if(o is Animal)
    Console.WriteLine("o is an animal");

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

if(o is Animal)
    ((Animal)o).Speak();

නමුත් එමඟින් සීඑල්ආර් වස්තුවේ වර්ගය දෙවරක් පරීක්ෂා කරයි. එය isක්‍රියාකරු තෘප්තිමත් කිරීම සඳහා වරක් එය පරික්ෂා කරනු ඇති අතර , oඇත්ත වශයෙන්ම එය නම් Animal, වාත්තු කිරීම වලංගු කිරීම සඳහා අපි එය නැවත පරීක්ෂා කරමු.

ඒ වෙනුවට මෙය කිරීම වඩාත් කාර්යක්ෂම වේ:

Animal a = o as Animal;
if(a != null)
    a.Speak();

මෙම asක්රියාකරු වෙනුවට නැවත, එය අපොහොසත් වන්නේ නම්, ව්යතිරේකයක් විසි නොවන බව ඉතා අයගේ ක්රමය null. මේ ආකාරයෙන්, සීඑල්ආර් වස්තුවේ වර්ගය එක් වරක් පමණක් පරීක්ෂා කරන අතර, ඉන් පසුව, අප විසින් ශුන්‍ය පරීක්‍ෂණයක් කළ යුතු අතර එය වඩාත් කාර්යක්ෂම වේ.

නමුත් පරෙස්සම් වන්න: බොහෝ අය උගුලකට හසු වේ as. එය ව්‍යතිරේකයන් නොදක්වන නිසා, සමහර අය එය "ආරක්ෂිත" කාස්ට් එකක් ලෙස සිතන අතර, ඔවුන් එය තනිකරම භාවිතා කරයි. මෙය මෙවැනි දෝෂ වලට තුඩු දෙයි:

(o as Animal).Speak();

මෙම අවස්ථාවේ දී, සංවර්ධකයා පැහැදිලිවම උපකල්පනය කරන්නේ oඑය සැමවිටම එකක් වනු ඇති Animalඅතර ඔවුන්ගේ උපකල්පනය නිවැරදිව පවතින තාක් කල් සියල්ල හොඳින් ක්‍රියාත්මක වන බවයි. නමුත් ඔවුන් වැරදියි නම්, ඔවුන් මෙහි අවසන් වන්නේ අ NullReferenceException. නිතිපතා වාත්තු කිරීමක් සමඟ, ඔවුන් ඒ InvalidCastExceptionවෙනුවට ලබා ගනු ඇත, එමඟින් ගැටළුව වඩාත් නිවැරදිව හඳුනා ගනු ඇත.

සමහර විට, මෙම දෝෂය සොයා ගැනීම දුෂ්කර විය හැකිය:

class Foo{
    readonly Animal animal;

    public Foo(object o){
        animal = o as Animal;
    }

    public void Interact(){
        animal.Speak();
    }
}

මෙය සෑම අවස්ථාවකදීම සංවර්ධකයා පැහැදිලිවම අපේක්ෂා oකරන තවත් Animalඅවස්ථාවකි, නමුත් asවාත්තු භාවිතා කරන ඉදිකිරීම්කරු තුළ මෙය පැහැදිලිව පෙනෙන්නට නැත . ක්ෂේත්‍රය ධනාත්මකව පවරනු ඇතැයි අපේක්ෂා කරන Interactක්‍රමයට ඔබ පිවිසෙන තුරු එය පැහැදිලිව පෙනෙන්නට නැත animal. මෙම අවස්ථාවේ දී, ඔබ නොමඟ යවන ව්‍යතිරේකයකින් අවසන් වනවා පමණක් නොව, සත්‍ය දෝෂය සිදුවූ කාලයට වඩා බොහෝ කලකට පසුව එය විසි නොකරයි.

සාරාංශයකින්:

  • වස්තුවක් කිසියම් වර්ගයකද නැද්ද යන්න ඔබට දැන ගැනීමට අවශ්‍ය නම් භාවිතා කරන්න is.

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

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


(o යනු සත්ව) ((සත්ව) o) නම් මෙහි ඇති වැරැද්ද කුමක්ද? කථා කරන්න (); ? කරුණාකර වැඩි විස්තර ලබා දිය හැකිද?
batmaci

2
at බාට්මාසි: එය පිළිතුරෙහි ඇත - එය වර්ග දෙකක චෙක්පත් ඇති කරයි. පළමු අවස්ථාව මෙය o is Animalවන විචල්ය වර්ගය නම් පරීක්ෂා කිරීම සඳහා CLR අවශ්ය වන, oයනු Animal. එය පරීක්ෂා කරන දෙවන අවස්ථාව එය ප්‍රකාශයේ සටහන් වන විට ය ((Animal)o).Speak(). දෙවරක් පරීක්ෂා කරනවා වෙනුවට, වරක් භාවිතා කර පරීක්ෂා කරන්න as.
සර්

මෙය නියත වශයෙන්ම විශිෂ්ට පැහැදිලි කිරීමක් ලෙස මට පෙනී ගියේය, පැහැදිලි කිරීම සඳහා ස්තූතියි!
පෝල් එෆෝඩ්

16

ඔබ C # 7 භාවිතා කරන්නේ නම්, ඇන්ඩ rew හාරේගේ විශිෂ්ට පිළිතුර යාවත්කාලීන කිරීමට කාලයයි. රටා ගැලපීම මඟින් කදිම කෙටිමඟක් හඳුන්වා දී ඇති අතර එය වෙනම ප්‍රකාශයක් / වාත්තු කිරීමක් අවශ්‍ය නොවී if ප්‍රකාශයේ සන්දර්භය තුළ ටයිප් කළ විචල්‍යයක් ලබා දෙයි:

if (obj1 is int integerValue)
{
    integerValue++;
}

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

Button button = obj1 as Button;
if (button != null)
{
    // do stuff...
    return;
}
TextBox text = obj1 as TextBox;
if (text != null)
{
    // do stuff...
    return;
}
Label label = obj1 as Label;
if (label != null)
{
    // do stuff...
    return;
}
// ... and so on

මෙම කේතය හැකිතාක් හැකිලීම වටා වැඩ කිරීම මෙන්ම එකම වස්තුවක අනුපිටපත් වළක්වා ගැනීම මට නිතරම කරදරයක් විය. ඉහත කරුණු පහත දැක්වෙන රටාවන්ට ගැලපෙන පරිදි සම්පීඩිත වේ:

switch (obj1)
{
    case Button button:
        // do stuff...
        break;
    case TextBox text:
        // do stuff...
        break;
    case Label label:
        // do stuff...
        break;
    // and so on...
}

සංස්කරණය කරන්න: පැලෙක්ගේ අදහස් අනුව ස්විචයක් භාවිතා කිරීම සඳහා දීර් new නව ක්‍රමය යාවත්කාලීන කරන ලදි.


1
මෙම අවස්ථාවේ දී switchරටා ගැලපීම සමඟ ප්‍රකාශය භාවිතා කිරීම සුදුසුය.
පලෙක්

එසේ නොවන්නේ කෙසේද? මෙම විශේෂිත කේත කොටසෙහි? if (obj1 is int integerValue) { integerValue++; }
බෙන් වර්ටොන්ගන්

බෙන්, මම ඔබේ ප්‍රශ්නය තේරුම් ගත්තා නම්, වෙනත් සංඛ්‍යා හැසිරවීමට මට වෙනත් ප්‍රකාශයක් තිබිය යුතුය. :)
JoelC

14

මට Typeසංසන්දනය කිරීමට -ප්‍රතිලාභයක් ඇති අතර is(වැනි my_type is _BaseTypetoLookFor) භාවිතා කිරීමට නොහැකි විය, නමුත් මට මේවා භාවිතා කළ හැකිය:

base_type.IsInstanceOfType(derived_object);
base_type.IsAssignableFrom(derived_type);
derived_type.IsSubClassOf(base_type);

සිටින බව දැනුම් IsInstanceOfTypeසහ IsAssignableFromනැවත trueIsSubClassOf ආපසු වන අතර එහිදී එම වර්ග, සාපේක්ෂව false. හා IsSubclassOfඅනෙක් දෙක කරන්න එහිදී අතුරු මුහුණත් මත වැඩ කරන්නේ නැහැ. ( මෙම ප්‍රශ්නය සහ පිළිතුරද බලන්න .)

public class Animal {}
public interface ITrainable {}
public class Dog : Animal, ITrainable{}

Animal dog = new Dog();

typeof(Animal).IsInstanceOfType(dog);     // true
typeof(Dog).IsInstanceOfType(dog);        // true
typeof(ITrainable).IsInstanceOfType(dog); // true

typeof(Animal).IsAssignableFrom(dog.GetType());      // true
typeof(Dog).IsAssignableFrom(dog.GetType());         // true
typeof(ITrainable).IsAssignableFrom(dog.GetType()); // true

dog.GetType().IsSubclassOf(typeof(Animal));            // true
dog.GetType().IsSubclassOf(typeof(Dog));               // false
dog.GetType().IsSubclassOf(typeof(ITrainable)); // false

9

මම කැමති කියන්නේ

එයින් කියැවෙන්නේ ඔබ භාවිතා කරන්නේ නම් , ඔබ උරුමය නිසි ලෙස භාවිතා නොකරන බවයි.

එම පුද්ගලයා උපකල්පනය කරන්න: ආයතනය, සහ එම සත්වයා: වස්තුව. සංග්‍රහය යනු ආයතනයේ අතථ්‍ය ක්‍රමයකි (නීල් සතුටු කිරීමට)

class Person
{
  // A Person should be able to Feed
  // another Entity, but they way he feeds
  // each is different
  public override void Feed( Entity e )
  {
    if( e is Person )
    {
      // feed me
    }
    else if( e is Animal )
    {
      // ruff
    }
  }
}

ඒ වෙනුවට

class Person
{
  public override void Feed( Person p )
  {
    // feed the person
  }
  public override void Feed( Animal a )
  {
    // feed the animal
  }
}

1
පුද්ගලයා සත්වයාගෙන් උපුටා ගත් බව දැන, මම කිසි විටෙකත් කලින් කළ දේ නොකරන බව ඇත්තකි.
jasonh

3
දෙවැන්න ඇත්ත වශයෙන්ම උරුමය භාවිතා නොකරයි. Foo යනු පුද්ගලයා සහ සත්වයන් අභිබවා යන අථත්‍ය ක්‍රමයකි.
නීල් විලියම්ස්

2
obbobobobo මම හිතන්නේ ඔබ අදහස් කළේ "අධික ලෙස පැටවීම" මිස "උරුමය" නොවේ.
එල්සී.

@lc: නැහැ, මම අදහස් කළේ උරුමයයි. පළමු උදාහරණය වෙනස් හැසිරීම් ලබා ගැනීම සඳහා වැරදි ක්‍රමයක් (භාවිතා කිරීම ) වේ. දෙවන උදාහරණය භාවිත ඔව් වැඩියෙන්, නමුත් වැලකී සිටීමේ භාවිතා කිරීම කියන්නේ .
bobobobo

1
උදාහරණයේ ඇති ගැටළුව නම් එය පරිමාණය නොකිරීමයි. ඔබ කෑමට අවශ්‍ය නව ආයතන එකතු කළහොත් (නිදසුනක් ලෙස කෘමියෙකු හෝ යක්ෂයෙක්) ඔබට ආයතන පන්තියේ නව ක්‍රමයක් එකතු කළ යුතු අතර එය පෝෂණය කරන උප පංතිවල එය අභිබවා යන්න. (වස්තුව යනු Y නම්) මෙය වෙනත් ලැයිස්තුවකට වඩා සුදුසු නොවේ ... මෙය LSP සහ OCP උල්ලං lates නය කරයි, උරුමය බොහෝ විට ගැටලුවට හොඳම විසඳුම නොවේ. යම් ආකාරයක නියෝජිත පිරිසක් කැමති වනු ඇත.
ebrown

5

මම විශ්වාස කරන්නේ අන්තිමයා උරුමය දෙස බලන බවයි (උදා: බල්ලා යනු සත්ව == සත්‍යය), එය බොහෝ අවස්ථාවන්හිදී වඩා හොඳය.


2

එය මා කරන දේ මත රඳා පවතී. මට bool අගයක් අවශ්‍ය නම් (කියන්න, මම int එකකට දමන්නේද යන්න තීරණය කිරීම සඳහා), මම භාවිතා කරමි is. කිසියම් හේතුවක් නිසා මට ඇත්ත වශයෙන්ම වර්ගය අවශ්‍ය නම් (කියන්න, වෙනත් ක්‍රමයකට යොමු වීමට) මම භාවිතා කරමි GetType().


1
හොඳ කරුණක්. වර්ගයක් පරීක්ෂා කිරීම සඳහා if ප්‍රකාශයක් භාවිතා කළ පිළිතුරු කිහිපයක් බැලීමෙන් පසුව මෙම ප්‍රශ්නයට මා යොමු වූ බව සඳහන් කිරීමට මට අමතක විය.
jasonh

0

අන්තිම එක පිරිසිදුයි, වඩා පැහැදිලිව පෙනෙන අතර උප වර්ග සඳහාද පරික්ෂා කරයි. අනෙක් අය බහුමාපකය පරීක්ෂා නොකරයි.


0

System.Type වස්තුව ලබා ගැනීම සඳහා භාවිතා වේ. යතුරු ලියනයක ප්‍රකාශනය පහත දැක්වෙන ස්වරූපය ගනී:

System.Type type = typeof(int);

Example:

    public class ExampleClass
    {
       public int sampleMember;
       public void SampleMethod() {}

       static void Main()
       {
          Type t = typeof(ExampleClass);
          // Alternatively, you could use
          // ExampleClass obj = new ExampleClass();
          // Type t = obj.GetType();

          Console.WriteLine("Methods:");
          System.Reflection.MethodInfo[] methodInfo = t.GetMethods();

          foreach (System.Reflection.MethodInfo mInfo in methodInfo)
             Console.WriteLine(mInfo.ToString());

          Console.WriteLine("Members:");
          System.Reflection.MemberInfo[] memberInfo = t.GetMembers();

          foreach (System.Reflection.MemberInfo mInfo in memberInfo)
             Console.WriteLine(mInfo.ToString());
       }
    }
    /*
     Output:
        Methods:
        Void SampleMethod()
        System.String ToString()
        Boolean Equals(System.Object)
        Int32 GetHashCode()
        System.Type GetType()
        Members:
        Void SampleMethod()
        System.String ToString()
        Boolean Equals(System.Object)
        Int32 GetHashCode()
        System.Type GetType()
        Void .ctor()
        Int32 sampleMember
    */

සංඛ්‍යාත්මක ගණනය කිරීමේ ප්‍රති result ල අඩංගු කිරීම සඳහා භාවිතා කරන වර්ගය තීරණය කිරීම සඳහා මෙම නියැදිය GetType ක්‍රමය භාවිතා කරයි. මෙය ප්‍රති ing ලයක් ලෙස ලැබෙන අංකයේ ගබඩා අවශ්‍යතා මත රඳා පවතී.

    class GetTypeTest
    {
        static void Main()
        {
            int radius = 3;
            Console.WriteLine("Area = {0}", radius * radius * Math.PI);
            Console.WriteLine("The type is {0}",
                              (radius * radius * Math.PI).GetType()
            );
        }
    }
    /*
    Output:
    Area = 28.2743338823081
    The type is System.Double
    */

-4
if (c is UserControl) c.Enabled = enable;

4
කරුණාකර වැඩි විස්තර සමඟ සංස්කරණය කරන්න. කේත-පමණක් සහ "මෙය උත්සාහ කරන්න" පිළිතුරු අධෛර්යමත් වේ, මන්ද ඒවායේ සෙවිය හැකි අන්තර්ගතයක් නොමැති අතර යමෙකු "මෙය උත්සාහ කළ යුත්තේ" මන්දැයි පැහැදිලි නොකරන්න.
abarisone

ඔබේ පිළිතුර ප්‍රශ්නයට සම්බන්ධ නැත.
menxin

-5

ඔබට C # හි "typeof ()" ක්‍රියාකරු භාවිතා කළ හැකි නමුත් ඔබට System.IO භාවිතා කර නාම අවකාශය ඇමතිය යුතුය; ඔබට වර්ගයක් පරීක්ෂා කිරීමට අවශ්‍ය නම් "is" යතුර භාවිතා කළ යුතුය.


7
typeofනාම අවකාශයක අර්ථ දක්වා නැත, එය යතුරු පදයකි. System.IOමේකට කිසිම සම්බන්ධයක් නැහැ.
ආටුරෝ ටොරස් සාන්චෙස්

-5

GetType () එදිරිව කාර්ය සාධන පරීක්ෂණ වර්ගය ():

using System;
namespace ConsoleApplication1
    {
    class Program
    {
        enum TestEnum { E1, E2, E3 }
        static void Main(string[] args)
        {
            {
                var start = DateTime.UtcNow;
                for (var i = 0; i < 1000000000; i++)
                    Test1(TestEnum.E2);
                Console.WriteLine(DateTime.UtcNow - start);
            }
            {
                var start = DateTime.UtcNow;
                for (var i = 0; i < 1000000000; i++)
                    Test2(TestEnum.E2);
                Console.WriteLine(DateTime.UtcNow - start);
            }
            Console.ReadLine();
        }
        static Type Test1<T>(T value) => typeof(T);
        static Type Test2(object value) => value.GetType();
    }
}

නිදොස් කිරීමේ මාදිලියේ ප්‍රති Results ල:

00:00:08.4096636
00:00:10.8570657

මුදා හැරීමේ මාදිලියේ ප්‍රති Results ල:

00:00:02.3799048
00:00:07.1797128

1
කාර්ය සාධන මිනුම් සඳහා යමෙකු DateTime.UtcNow භාවිතා නොකළ යුතුය. ඔබේ කේතය සමඟ නමුත් Stopwatch පන්තිය සමඟ මට දෝශ නිරාකරණ මාදිලිය සඳහා ප්‍රතිවිරුද්ධ ප්‍රති results ල ලැබුණි. UseTypeOf: 00: 00: 14.5074469 UseGetType: 00: 00: 10.5799534. මුදා හැරීමේ මාදිලිය බලාපොරොත්තු වූ පරිදිම වේ
ඇලෙක්සි ෂර්බක්

LexAlexeyShcherbak Stopwatch සහ DateTime අතර වෙනස. දැන් 10-20 ms ට වඩා වැඩි විය නොහැක, ඔබේ කේතය නැවත පරීක්ෂා කරන්න. මගේ පරීක්ෂණයෙන් මිලි තත්පර ගැන මම තැකීමක් නොකරමි. මගේ කේතය Stopwatch සමඟ කේත පේළි කිහිපයක් වනු ඇත.
ඇලෙක්සැන්ඩර් වාසිලියෙව්

1
එය සාමාන්‍යයෙන් නරක පුරුද්දකි, ඔබේ විශේෂිත අවස්ථාවෙහිදී නොවේ.
ඇලෙක්සි ෂර්බක්

4
Lex ඇලෙක්සැන්ඩර් වැසිලීව් ලේඛනගත ලෙස නොමඟ යවන යමක් කිරීමට කේත රේඛා ප්‍රමාණය කිසි විටෙකත් තර්කයක් ලෙස භාවිතා නොකළ යුතුය . Msdn.microsoft.com/en-us/library/system.datetime(v=vs.110).aspx හි දැක ඇති පරිදි , DateTimeඔබ මෙහෙයුම් පද්ධතියේ කාල රාමුව භාවිතා කරන බැවින්, මීටර 100 ට අඩු වේලාවන් ගැන සැලකිලිමත් වන්නේ නම් එය භාවිතා නොකළ යුතුය . Stopwatchප්‍රොසෙසර භාවිතා කරන සාපේක්ෂව , වින් 7 හි Tickභාවිතා කරන විභේදනය DateTimeමීටර් 15 කි.
එරික් වු
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.