10
votes

La classe n'hérite pas de l'objet?

Je travaille sur une méthode qui utilise la réflexion pour inspecter les types de méthodes de paramètre. Ces méthodes tiendrent via le paramètreinfo et font quelque chose avec les types de ces paramètres.

J'étais toujours sous l'hypothèse que si typeinfo.isclass est vrai , que cela Type est une classe et dérive toujours (indirectement) à partir de type objet (sauf lorsque le type est objet bien sûr). Donc, si typeinfo.isclass est vrai, typeinfo.basetype doit être défini.

Eh bien, mon hypothèse était fausse! Il existe des cours qui ne dérivent pas de type objet . Et mon hypothèse falsifie mon code.

Par exemple: xxx

type.isclass sera vrai < / code> et type.baseType sera null .

Si vous y pensez, il est logique. Et je peux empêcher mon code de s'écraser en cochant typeinfo.isbyref .

ma question est la suivante: existe-t-il plus de ces types "exotiques" (avantageux des types de byref et tapez objet ) qui sont une classe ( isclass == true ) mais ne possédez pas de type de base ( baseType == null )? < / strong>

Avant de répondre: je ne fais que référence à des types où isclass == true ! Et mon exemple avec type int n'était qu'un exemple. Cela aurait pu être n'importe quel type. Alors s'il vous plaît non:

  • interfaces
  • structs
  • void

    réponses jusqu'à présent:

    • Types BYREF ( T & ): En tant que descendant dans la question.
    • Types de pointeur ( T * ): Trouvé par Mark Gravell.

18 commentaires

Toute référence-to- Types de valeur à coup sûr. En outre, le type " annulation référence".


Juste une suppose, mais avez-vous vérifié le type dynamique?


@ user287107: dynamique est identique à celui de en ce qui concerne le système de type.


@Jon: Tous les types de valeur dérivent indirectement de objet . Un type de valeur dérive de valueltype et valeur de type dérive de objet .


@MartinMulder: J'ai édité le commentaire pour être plus précis; Je voulais dire "types de type de référence à valeur", comme dans votre exemple.


@Jon: typoef (void) .isclass ==> false .


@MartinMulder: typeof (vide) .MakeByReftype (). Isclass ==> true .


@Jon Pouvez-vous créer un lien vers la documentation qui stipule que tous les types Types n'héritent pas de objet (ou affichent ce comportement)?


@MartinMulder: Concernant la modification - J'espère que vous réalisez que int est également une structure et la seule chose qui fait isclass vrai est le < Code> MakeByRefType () .


@Dialer: Non, je n'ai que l'observation seulement. N'a rien trouvé de pertinent avec une recherche rapide sur MSDN.


@Jon: À propos du Void.MakeByReftype ... C'est la même chose que j'ai déjà dans ma question. TOUT BYREFTYPE est une classe. (Très curieux dans ce que World une référence au vide serait utile, mais c'est une autre affaire.)


Question intéressante, ne mérite pas les bowvotes, imo


@MartinMulder: Je pense que vous devriez supprimer la liste à la fin de la question - ce n'est pas vraiment utile - et le remplacer par «Je suis intéressé par tout ce qui n'est pas le résultat de l'appelant MakebyRefType ()`.


Downvoteurs, veuillez commenter pourquoi.


@Jon: Eh bien ... ma liste ne devrait pas être là, mais j'ai déjà eu deux réponses: une référence: une référence à des interfaces (dont ISClass == false), et l'autre était sur objet , que j'ai déjà co-donné dans ma question.


@MartinMulder Celui que vous dites est "À propos des interfaces" Citations MSDN disant "L'objet est le seul type qui n'a pas de type de base, donc NULL est renvoyé comme type de base de l'objet.", Qui, comme je l'ai signalé Un commentaire est une réponse précise à votre question. Que voulez-vous de plus?


@Danieldaranas Il semble que n'importe quel type Typename & (que vous obtenez de typeof (typename) .MakeBeReftype () a isclass == true et baseType == null . C'est intéressant, mais je ne trouve rien dans la documentation à ce sujet (nous devrions peut-être essayer d'invoquer Jon Skeet). Cependant, il a aussi isbyref == true , vous pouvez donc vérifier cela aussi.


Downvoteurs, veuillez commenter.


3 Réponses :


14
votes

Je dirais que isclass code> est simplement trompeur ici. Il indique:

obtient une valeur indiquant si le système.Type est une classe; c'est-à-dire non pas de type de valeur ni d'interface. P> blockQuote>

et il est mis en œuvre em> P>

Malheureusement, il y a plus de choses que cela. Les pointeurs ne sont pas des types gérés em>. Un by-ref est très similaire à un pointeur. Le pointeur ne sont pas objet code> S, bien que en commun, la distribution est en réalité une référence / moulée. Il en va de même pour des éléments comme des pointeurs directs tels que int * code>. P>

pas tout dans .NET est un objet code> :) p>

var baseType = typeof(int*).BaseType; // null
bool liesAndMoreLies = typeof(int*).IsClass; // true


1 commentaires

@MartinMulder pendant un moment là, je pensais que cela a signalé isclass comme false , mais il rapporte en réalité vrai - c'est vraiment beaucoup la même chose que le type exotique dans la question



-1
votes

Type.getelementType Méthode (de MSDN)

Le type de l'objet englobé ou mentionné par la matrice, le pointeur ou le type de référence actuel, ou NULL si le type de courant n'est pas un tableau ou un pointeur, ou n'est pas transmis par référence ou représente un type générique ou Paramètre de type dans la définition d'un type générique ou d'une méthode générique.

code ... xxx


22 commentaires

Comment est-ce une réponse à ma question? Je cherche des types plus exotiques. Pas un moyen de changer de type exotique à un type normal.


Vous avez dit qu'il y a des cours qui ne dérivent pas d'objet. Il me semble que vous avez boxé un entier et que vous enquêtez sur le type de base du mauvais sens. Il y a un type de base.


Vos types exotiques n'existent pas. L'objet est le seul type qui n'a pas de type de base. Pourquoi ne répondez-vous pas à mon dernier commentaire et expliquez-vous ensuite votre bowvote.


Ils n'existent pas? Vous affirmez donc que mon exemple de code produira une exception d'exécution?


Enquêter sur le mauvais moyen? Je déclare simplement que le type exotique int & est marqué comme une classe mais n'a pas de type de base. Je demande simplement s'il y a plus de ces types exotiques. Je ne demande pas comment les analyser.


Définir exotique? Vous dites qu'ils sont "exotiques" car isclass == true tandis que le type de base est null. Tort! Le type de base n'est pas nul. Lorsque vous boxez un entier, le type de base est évalué différemment, comme je l'ai posté ci-dessus.


Avez-vous même testé? Vous dites typeinfo.basetype n'est pas null ... Testez-le simplement. Créer un programme qui écrira iSclass et BaseType à la console et voyez si elles sont true + null ou non .


Je parierais que les gars qui ont construit le framework .NET ont des idées à cela. Si j'appelle GetElementtype (), puis vérifiez le babeype, cela ne sera pas null. Que supposez-vous que getElementtype () est pour?


Je l'ai testé ... et j'ai collé le code ci-dessus et iSclass == True et après avoir appelé GetElementtype () et vérifiant le BaseType ... ce n'est pas null mais montre le type de base exact que j'attendrais.


GetElementtype () n'a rien à voir avec ça. getElementtype () est utilisé pour obtenir le type d'élément d'un tableau. Ou un type de référence. Donc, dans ce cas getElementtype et MakeBeRefType sont les autres compléter les fonctions. Ils retournent tous les deux un type. De ces types n'a pas de base de base.


Ma question est la suivante: Y a-t-il des types plus «exotiques» (et je définis dans ma question ce que je veux dire par cela). Où est votre question? Où est le type de sortie de sortie que vous avez trouvé?


MakebYreftype va faire un type de référence d'un type. GetElementtype obtient le type de l'objet mentionné par le type de référence.


Je comprends votre question mais votre définition des types exotiques n'a aucun sens, car vous utilisez MakeBeRefType pour créer un type et refuser d'utiliser GetElementtype pour obtenir le type à partir de laquelle vous pouvez déterminer son type de base.


Ensuite, vous n'obtenez pas ma question.


Question: Maintenant, ma question est la suivante: Y a-t-il plus de types de "types exotiques" (avantageux des types de byref-types et de type) qui sont une classe (isclass == true) mais n'ont pas de type de base (BaseType == Null)? Réponse: Les types de type BYREF et les types de type ont des types de base, votre question implique qu'ils ne l'utilisent pas, mais le fait est que vous n'utilisez pas GetElementtype qui est la bonne façon de déterminer le type de base des types de byref.


J'ai créé une liste de réponses correctes. Assurez-vous de trouver une autre réponse pour que je puisse vous mettre dans la liste. Tous les autres commentaires ou réponses sur la manière de trouver un type de base Une autre manière ne sont pas des réponses correctes!


Pourquoi n'essayez-vous pas au moins getElementtype () ... Voir si vous obtenez le type de base que vous attendez. GetElementtype () est également nécessaire lors de la gestion des pointeurs lorsque vous souhaitez obtenir le type de base.


Je sais comment getElementtype () fonctionne. Je savais déjà avant de poser la question. Donc, je ne cherche pas une explication de cela.


@ user2315985 Lorsque vous écrivez une méthode qui accepte simplement un type type , vous ne pouvez pas faire d'autres hypothèses sur ce type type . Par exemple, vous ne pouvez pas faire getElementtype car vous ne savez pas s'il y a un type d'élément. Ainsi, en utilisant uniquement isclass et bascule , pouvez-vous trouver plus d'instances de type pour quel isclass est vrai et BaseType est null?


Vous l'avez dit dans votre propre message ... "Il y a des cours qui ne dérivent pas d'objet de type". Pourtant, si vous utilisez GetElementtype () et vérifiez le type de base, il n'est pas nul et renvoie la classe de base appropriée comme prévu. Si vous comprenez GetElementtype () Pourquoi dans le monde ne l'utiliseriez-vous pas? Au lieu de cela, vous pensez que certaines classes exotiques existent, qui n'ont pas de type de base? Fait: Outre l'objet, tous les types ont un type de base. Objet ne le fait pas. Si vous vérifiez un type de référence après l'utilisation de MakeByRefType, la bonne façon de vérifier la classe de base de l'objet mentionné par la classe de base est d'utiliser getElementtype


@user: Je suis au courant de la fonction getElementtype et de ce que cela fait. Je le savais avant de poster cette question. Je suis absent qui, en utilisant cette fonction, je peux obtenir le type de base de l'élément du type de référence. Mais je ne suis pas intéressé à trouver des types de base d'éléments. Je ne suis intéressé que par des types exotiques tels que définis dans ma question. Si vous postez une réponse avec un nouveau type exotique, je vais y mettre votre réponse aussi.


Eh bien, vous n'avez que deux choses répertoriées, des types de référence et des pointeurs, qui ne sont ni exotiques et qui font tous deux référence aux objets qui ont un type de base. Ils ne sont pas mystérieux ou étrange ... ils sont bien documentés sur MSDN afin que vous puissiez les renommer d'exotiques à autre chose.



2
votes

Sauf Types génériques qui ne sont pas instanciés, est signalé avec le lien Ce n'est pas tout issu de l'objet @ M. LIPPERT's Blog par MR. La bonne réponse de gravell , je suggère que la recherche des autres types remplis de votre condition peut être effectuée par vous-même.

Maintenant, commençons à partir de zéro pour résoudre cette question. Tout d'abord, les types que vous allez comprendre, devraient être dans la bibliothèque d'exécution principale et qui est mscorlib.dll code>: p> xxx pré>

et Ensuite, les types ont les méthodes makexxxxtype () code> tels que makebyreftype () code>. Ici, nous prenons plus de possibilités de possibilité, c'est n'importe quelle méthode forte> qui retourne type ou types fort>. Depuis que nous connaissons zéro connaissances sur les arguments d'un type fort> de type arbitraire fort>, nous considérons méthodes prennent zéro argument strong>: p> xxx avant

pour La mise en œuvre de InvokeroargumentMethodwhichreturnstypeyTypes Code> Cependant, il existe plusieurs cas invalides de ce type d'invocation, tels que l'appelant getgenericparameterconstraints () code> sur un type non générique; Nous évigeons ces cas avec try-attrayez em>: p> xxx pré>

et maintenant, pour comprendre les types souhaités. Construisons la méthode étape par étape. La première étape définirait la portée de tous les types possibles: p> xxx pré>

puis, selon ce que vous avez déclaré essentiellement: P>

Maintenant ma question est la suivante: y a-t-il plus de ces types "exotiques" (avantageux des types de byref et type objet code>) qui sont une classe ( isclass == true code>) mais ne pas avoir de type de base ( fondype == null code>)? strong> p> blockquote> xxx pré>

Vous avez également indiqué que pour avant de répondre code>: p>

Avant de répondre: je ne fais que référence à des types où isclass == true code>! Et mon exemple avec type int code> n'était qu'un exemple. Cela aurait pu être n'importe quel type. Alors s'il vous plaît non: p>

  • interfaces li>
  • structs li>
  • void li> ul> blockQquote> xxx pré>

    L'étape finale, saute déjà répondu et compléter la méthode: p> xxx pré>

    alors maintenant, vous pouvez maintenant Invoquer martinmuldéréxtensions.getDésiredtypes () code> Pour obtenir les types que vous avez désirés: p> xxx pré>


    pour le code complet: p>

    public static partial class MartinMulderExtensions {
        public static IEnumerable<Type> GetMscorlibTypes() {
            return
                from assembly in AppDomain.CurrentDomain.GetAssemblies()
                let name=assembly.ManifestModule.Name
                where 0==String.Compare("mscorlib.dll", name, true)
                from type in assembly.GetTypes()
                select type;
        }
    
        public static IEnumerable<Type>
            InvokeZeroArgumentMethodWhichReturnsTypeOrTypes(
            this MethodInfo method, Type t
            ) {
            try {
                if(typeof(Type)==method.ReturnType) {
                    var type=method.Invoke(t, null) as Type;
    
                    if(null!=type)
                        return new[] { type };
                }
    
                if(typeof(Type[])==method.ReturnType) {
                    var types=method.Invoke(t, null) as Type[];
    
                    if(types.Length>0)
                        return types;
                }
            }
            catch(InvalidOperationException) {
            }
            catch(TargetInvocationException) {
            }
            catch(TargetException) {
            }
    
            return Type.EmptyTypes;
        }
    
        public static IEnumerable<Type> GetRetrievableTypes(this Type type) {
            var typesArray=(
                from method in type.GetMethods()
                where 0==method.GetParameters().Count()
    
                let typeArray=
                    method.InvokeZeroArgumentMethodWhichReturnsTypeOrTypes(type)
    
                where null!=typeArray
                select typeArray).ToArray();
    
            var types=
                typesArray.Length>0
                    ?typesArray.Aggregate(Enumerable.Union)
                    :Type.EmptyTypes;
    
            return types.Union(new[] { type });
        }
    
        public static Type[] GetDesiredTypes() {
            return (
                from type in MartinMulderExtensions.GetMscorlibTypes()
                .Select(x => x.GetRetrievableTypes())
                .Aggregate(Enumerable.Union)
    
                where null==type.BaseType
                where type.IsClass
                where !type.IsInterface
                where !type.IsValueType
                where typeof(void)!=type
    
                where !type.IsByRef
                where !type.IsPointer
    
                select type
                ).ToArray();
        }
    }
    


0 commentaires