Comment avoir le nom de l'instance qui appelle un function ?

Inscrit
4 Aout 2016
Messages
166
Reactions
0
#1
Bonjour,

Ça fait seulement 1 jour que j'apprend le C# et j'ai une question, peut être que le titre est mal expliqué donc comme l'a dit un grand sache un jour :
Un bout de code vaut plus que 10 000 mots
C#:
public class Vehicul
    {
        protected string modelName;
        protected string color;
        protected int wheels;
        protected int km;

        public void ShowInfo()
        {
            foreach(var prop in instance.GetType().GetProperties())
            {
                Console.WriteLine("{0} : {1}", prop.GetName, prop.GetValue);
            }
        }
    }
Et ensuite faire dans main :

C#:
Vehicul clio = new Vehicul(arg, arg, arg)
clio.ShowInfos;
Donc, ce que je veux c'est avoir la valeur de "instance", l'autre manière aurait été de déclarer la valeur en argument, mais je trouve ça moins pratique et esthétique, il doit sûrement y avoir une sorte de "self" ou autre pour avoir le nom de la variable vehicul qui appelle la function non ?

Notez que le code est incorrecte c'est juste pour vous montrer l'idée

Voilà j’espère que vous m'avez compris :)
 
Dernière édition:
Inscrit
2 Juin 2016
Messages
82
Reactions
3
#2
This
 
Inscrit
4 Aout 2016
Messages
166
Reactions
0
#3

Merci Brook, ducoup je partage ma function, elle pourra vous être utile :

C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Program
{
    // Notre class de base.
    class Vehicul
    {
        // Ne surtout pas oublier de les déclarer en "public", sinon on ne pourras pas acceder au types, properties.
        public int Km { get; set; }
        public string Name { get; set; }

        public Vehicul(int a_km, string a_name)
        {
            Km = a_km;
            Name = a_name;
        }

        public void ShowInfos()
        {
            // "this" sert à ne pas spécifier en argument de ShowInfo l'instance dont on veux afficher les attribus.
            foreach(var prop in this.GetType().GetProperties())
            {
                Console.WriteLine(prop.Name + " : " + prop.GetValue(this, null));
            }
        }
    }

    class Plane : Vehicul
    {
        public int SizeOfWings { get; set; }
        public string MotorType { get; set; }

        public Plane(int a_km, string a_name, int a_sizeOfWings, string a_motorType) : base(a_km, a_name)
        {
            SizeOfWings = a_sizeOfWings;
            MotorType = a_motorType;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Plane p = new Plane(0, "Airbus", 15, "Reaction");
            p.ShowInfos();

            // Et voilà ! On à maintenant une fonction qui peux lire tous les attribus d'une instance sans devoir spécifier les attribus à lire au paravant.
            Console.ReadKey();
        }
    }
}
 
Inscrit
2 Juin 2016
Messages
82
Reactions
3
#4
En soit, c'est cool ce que tu fais sauf que c'est pas du tout optimisé. c'est très lent au runtime car tu fais appel à la reflection. Pour optimiser, il faudrait utiliser une dynamic method ou une expression tree.

je te fournis un code pour t'expliquer tout cela ce soir
 
Inscrit
4 Aout 2016
Messages
166
Reactions
0
#5
En soit, c'est cool ce que tu fais sauf que c'est pas du tout optimisé. c'est très lent au runtime car tu fais appel à la reflection. Pour optimiser, il faudrait utiliser une dynamic method ou une expression tree.

je te fournis un code pour t'expliquer tout cela ce soir

Ok merci, je suis débutant en c# alors niveau opti.. x)
 
Inscrit
2 Juin 2016
Messages
82
Reactions
3
#6
C#:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Program
{
    // Notre class de base.
    class Vehicul
    {
        //some properties
        public int Km { get; set; }
        public string Name { get; set; }

        public Vehicul(int a_km, string a_name)
        {
            Km = a_km;
            Name = a_name;
        }

        public void ShowInfos()
        {
            // "this" sert à ne pas spécifier en argument de ShowInfo l'instance dont on veux afficher les attribus.
            foreach (var prop in this.GetType().GetProperties())
            {
                Console.WriteLine(prop.Name + " : " + prop.GetValue(this, null));
            }
        }
    }

    class Plane : Vehicul
    {
        public int SizeOfWings { get; set; }
        public string MotorType { get; set; }

        public Plane(int a_km, string a_name, int a_sizeOfWings, string a_motorType) : base(a_km, a_name)
        {
            SizeOfWings = a_sizeOfWings;
            MotorType = a_motorType;
        }
    }

    class Program
    {
        //"stupid benchmark" available at http://puu.sh/qs1o0/82bf284101.png
        static void Main(string[] args)
        {
            Plane p = new Plane(0, "Airbus", 15, "Reaction");
            int max_it = 100000;

            Stopwatch sw = new Stopwatch();
            sw.Start();

            for (int i = 0; i < max_it; i++)
            {
                p.ShowInfos();
            }

            sw.Stop();

            var old_way = sw.ElapsedMilliseconds;
            sw.Restart();

            for (int i = 0; i < max_it; i++)
            {
                p.Display();
                //u can use also this syntax: Displayer<Plane>.Display(p);
            }

            sw.Stop();

            var new_way = sw.ElapsedMilliseconds;

            Console.Clear();

            Console.WriteLine($"Old way : {old_way} ms \nNew way : {new_way} ms");
            Console.ReadLine();
        }
    }

    /// <summary>
    /// Generic displayer to display every properties of a type T.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public static class Displayer<T>
    {
        public static Action<T> Display { get; private set; }

        /*
         * Because Displayer<T> is static, the ctor is called once and before any methods/properties of the type.
         */
        static Displayer()
        {
            var t = typeof(T);
            var par_t = Expression.Parameter(t);

            var properties = t.GetProperties();

            List<Expression> calls = new List<Expression>(properties.Length);
            var cw_mi = typeof(Console).GetMethod("WriteLine", new[] { typeof(string), typeof(object[]) });
            foreach (var pi in properties)
            {
                var array_init = Expression.NewArrayInit(typeof(object),
                        Expression.Convert(Expression.Constant(pi.Name), typeof(object)),
                        Expression.Convert(Expression.Property(par_t, pi.Name), typeof(object)));

                calls.Add(Expression.Call(null, cw_mi, Expression.Constant("{0} - {1}"), array_init));
            }

            if (calls.Count > 0)
            {
                var block = Expression.Block(calls);

                Display = Expression.Lambda<Action<T>>(block, par_t).Compile();
            }
            else
                throw new ArgumentException($"No property to display for {t} type.");
        }
    }

    /// <summary>
    /// Extensions to sugar syntax
    /// </summary>
    public static class Extensions
    {
        public static void Display<T>(this T inst) => Displayer<T>.Display(inst);
    }
}
Voici ton code revu et corrigé, si tu as besoin de questions n'hésite pas. (c'est des trucs relativement avancés, ce n'est pas à la portée de tous mais c'est sympa à savoir)
 
Dernière édition:
Inscrit
4 Aout 2016
Messages
166
Reactions
0
#7
C#:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Program
{
    // Notre class de base.
    class Vehicul
    {
        //some properties
        public int Km { get; set; }
        public string Name { get; set; }

        public Vehicul(int a_km, string a_name)
        {
            Km = a_km;
            Name = a_name;
        }

        public void ShowInfos()
        {
            // "this" sert à ne pas spécifier en argument de ShowInfo l'instance dont on veux afficher les attribus.
            foreach (var prop in this.GetType().GetProperties())
            {
                Console.WriteLine(prop.Name + " : " + prop.GetValue(this, null));
            }
        }
    }

    class Plane : Vehicul
    {
        public int SizeOfWings { get; set; }
        public string MotorType { get; set; }

        public Plane(int a_km, string a_name, int a_sizeOfWings, string a_motorType) : base(a_km, a_name)
        {
            SizeOfWings = a_sizeOfWings;
            MotorType = a_motorType;
        }
    }

    class Program
    {
        //"stupid benchmark" available at http://puu.sh/qs1o0/82bf284101.png
        static void Main(string[] args)
        {
            Plane p = new Plane(0, "Airbus", 15, "Reaction");
            int max_it = 100000;

            Stopwatch sw = new Stopwatch();
            sw.Start();

            for (int i = 0; i < max_it; i++)
            {
                p.ShowInfos();
            }

            sw.Stop();

            var old_way = sw.ElapsedMilliseconds;
            sw.Restart();

            for (int i = 0; i < max_it; i++)
            {
                p.Display();
                //u can use also this syntax: Displayer<Plane>.Display(p);
            }

            sw.Stop();

            var new_way = sw.ElapsedMilliseconds;

            Console.Clear();

            Console.WriteLine($"Old way : {old_way} ms \nNew way : {new_way} ms");
            Console.ReadLine();
        }
    }

    /// <summary>
    /// Generic displayer to display every properties of a type T.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public static class Displayer<T>
    {
        public static Action<T> Display { get; private set; }

        /*
         * Because Displayer<T> is static, the ctor is called once and before any methods/properties of the type.
         */
        static Displayer()
        {
            var t = typeof(T);
            var par_t = Expression.Parameter(t);

            var properties = t.GetProperties();

            List<Expression> calls = new List<Expression>(properties.Length);
            var cw_mi = typeof(Console).GetMethod("WriteLine", new[] { typeof(string), typeof(object[]) });
            foreach (var pi in properties)
            {
                var array_init = Expression.NewArrayInit(typeof(object),
                        Expression.Convert(Expression.Constant(pi.Name), typeof(object)),
                        Expression.Convert(Expression.Property(par_t, pi.Name), typeof(object)));

                calls.Add(Expression.Call(null, cw_mi, Expression.Constant("{0} - {1}"), array_init));
            }

            if (calls.Count > 0)
            {
                var block = Expression.Block(calls);

                Display = Expression.Lambda<Action<T>>(block, par_t).Compile();
            }
            else
                throw new ArgumentException($"No property to display for {t} type.");
        }
    }

    /// <summary>
    /// Extensions to sugar syntax
    /// </summary>
    public static class Extensions
    {
        public static void Display<T>(this T inst) => Displayer<T>.Display(inst);
    }
}
Voici ton code revu et corrigé, si tu as besoin de questions n'hésite pas. (c'est des trucs relativement avancés, ce n'est pas à la portée de tous mais c'est sympa à savoir)

Wow, merci :)

Mais ça rajoute vraiment beaucoup de lignes pour gagner seulement 1/5 de seconde, c'est vraiment utiel ?
 
Inscrit
2 Juin 2016
Messages
82
Reactions
3
#8
Sauf qu'ici, le code est créer de façon à convenir à toutes les classes et de façon simple. De plus ici c'est inutile (l'overhead est en effet beaucoup trop important) mais pour réaliser d'autres systèmes (par exemple serializer auto) c'est facile et simple avec cette méthode !
 
Inscrit
4 Aout 2016
Messages
166
Reactions
0
#9
Sauf qu'ici, le code est créer de façon à convenir à toutes les classes et de façon simple. De plus ici c'est inutile (l'overhead est en effet beaucoup trop important) mais pour réaliser d'autres systèmes (par exemple serializer auto) c'est facile et simple avec cette méthode !
D'ac ! Si j'ai d'autres questions de noob je passerais par toi alors ! ;)
 
Inscrit
2 Juin 2016
Messages
82
Reactions
3
#10
C'est surtout le concept de classe générique statique qui est intéressant, proposant une alternative aux dictionnaires de delegates (comme on peut le voir dans stump) sans cast et thread safe!
 
Haut Bas