logo elektroda
logo elektroda
X
logo elektroda

[C#] Accessing Public Functions and Variables from Different Classes in Same Namespace

andros1245 21276 19
ADVERTISEMENT
Treść została przetłumaczona polish » english Zobacz oryginalną wersję tematu
  • #1 8876321
    andros1245
    Level 11  
    Hello!

    I'm just getting started with C#. I have several files merged into one project, with the same namespace but different classes. How to use a function in another class in another file? By the way, I will also ask how to use a variable located in another file?

    I will add that functions/procedures/variables have public status.

    Please help.
  • ADVERTISEMENT
  • #2 8876774
    dturczak
    Level 19  
    you can use the static modifier so you can call f/p/z through the class and not its object, but that's a bit unelegant..
    or just pass the instances of the class no through the constructor...
    (objects are passed by reference by default)

    class klasa1
    {
    public static int a;
    public int b;
    
    }
    class klasa2
    {
      klasa1 k1_ref;
    
      klasa2(klasa1 tmp)
      {
         k1_ref=tmp;
         System.out.print(klasa1.a);
         System.out.print(k1_ref.b);
      }
    }
    
    main()
    {
    klasa1.a=111;
    klasa1 k1=new klasa1();
    k1.b=222;
    klasa2 k2=new klasa2(k1);
    
    }


    read about mvc patterns, facade...
    makes your life easier :)
  • #3 8876807
    marcinj12
    Level 40  
    This question is a bit confusing :) If I understand correctly, you have two files with class A and class B, and you want to call a (public) method in class A and class B?
    If so, then - assuming class B is not static - while in class A you need to instantiate class B and call the method, no.
    
    KlasaB klasaB = new KlasaB();
    klasaB.WykonajMetode();
    


    Variables are best used with the use of accessors (you can also make the variable public, but it is not advisable :) ):
    
    public class KlasaB
    {
          public KlasaB()
          {
          }
    
          private int zminnaX;
          private int zmiennaY;
    
         //akcesory publiczne
         public int ZmiennaX { get { return zmiennaX; } set { zmiennaX = value; } }
        //tylko do odczytu
         public int ZmiennaY { get { return zmiennaY; }  }
    
    }
    
    
    //w klasie A:
    KlasaB klasaB = new KlasaB();
    klasaB.ZmiennaX = 10;
    int a = klasaB.ZmiennaY;
    
  • #4 8877186
    andros1245
    Level 11  
    marcinj12 wrote:
    This question is a bit confusing :) If I understand correctly, you have two files with class A and class B, and you want to call a (public) method in class A and class B?
    If so, then - assuming class B is not static - while in class A you need to instantiate class B and call the method, no.
    
    KlasaB klasaB = new KlasaB();
    klasaB.WykonajMetode();
    


    Variables are best used with the use of accessors (you can also make the variable public, but it is not advisable :) ):
    
    public class KlasaB
    {
          public KlasaB()
          {
          }
    
          private int zminnaX;
          private int zmiennaY;
    
         //akcesory publiczne
         public int ZmiennaX { get { return zmiennaX; } set { zmiennaX = value; } }
        //tylko do odczytu
         public int ZmiennaY { get { return zmiennaY; }  }
    
    }
    
    
    //w klasie A:
    KlasaB klasaB = new KlasaB();
    klasaB.ZmiennaX = 10;
    int a = klasaB.ZmiennaY;
    


    Thank you very much for your help :)
    However, I have a problem: the class does not contain any input arguments and the compiler returns an error when trying to new ClassB():
    'Program.KlasaB' does not contain a constructor that takes '1' arguments


    Class declaration:
    class KlasaB

    At this point, I can't flag it as public because the functions are similar in both classes.
  • ADVERTISEMENT
  • #5 8877210
    marcinj12
    Level 40  
    Post the code if you can, you don't accidentally give an argument somewhere in the class constructor call?
    The class does not necessarily have to be flagged as public, if you do not provide anything, the compiler will assign it the internal level by default, i.e. a class visible inside the entire assembly (but not outside - i.e. you will not include it as a .dll library in another project)
  • ADVERTISEMENT
  • #6 8877336
    andros1245
    Level 11  
    This is the code from XNA slightly reworked:

     class Gem
        {
            private Texture2D texture;
            private Vector2 origin;
            private SoundEffect collectedSound;
            private SoundEffect SuperMoc;
    
            public readonly int PointValue;
            public bool IsPowerUp { get; private set; }
            public readonly Color Color;
    
    
            private Vector2 basePosition;
            private float bounce;
    
            public Level Level
            {
                get { return level; }
            }
            Level level;
    
            public Vector2 Position
            {
                get
                {
                    return basePosition + new Vector2(0.0f, bounce);
                }
            }
    
            public Circle BoundingCircle
            {
                get
                {
                    return new Circle(Position, Tile.Width / 3.0f);
                }
            }
    
            public Gem(Level level, Vector2 position, bool isPowerUp)
            {
                this.level = level;
                this.basePosition = position;
    
                IsPowerUp = isPowerUp;
                if (IsPowerUp)
                {
                    PointValue = 100;
                    Color = Color.Red;
                }
                else
                {
                    PointValue = 30;
                    Color = Color.Yellow;
                }
    
                LoadContent();
            }
    
            public void LoadContent()
            {
                texture = Level.Content.Load("Postacie/Diament");
                origin = new Vector2(texture.Width / 2.0f, texture.Height / 2.0f);
                collectedSound = Level.Content.Load("Sounds/Zdobyty");
                SuperMoc = Level.Content.Load("Sounds/Moc_efekt");
            }
    
            public void Update(GameTime gameTime)
            {
                const float BounceHeight = 0.18f;
                const float BounceRate = 3.0f;
                const float BounceSync = -0.75f;
               
                double t = gameTime.TotalGameTime.TotalSeconds * BounceRate + Position.X * BounceSync;
                bounce = (float)Math.Sin(t) * BounceHeight * texture.Height;
            }
    
            public void OnCollected(Player collectedBy)
            {
                collectedSound.Play();
                
             
                if (IsPowerUp)
                {
                    collectedBy.PowerUp();
                }
            }
    
            public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
            {
                spriteBatch.Draw(texture, Position, null, Color, 0.0f, origin, 1.0f, SpriteEffects.None, 0.0f);
            }
        }
  • #7 8877596
    marcinj12
    Level 40  
    OK, but where do you get the error message?
    Also, you write that you have code in two classes/files, and this is one class.
  • #8 8878633
    andros1245
    Level 11  
    Gem diamenty = new Gem();

    It's about that parenthesis. You can't compile without it, but you can't with it either.

    public class PlatformerGame : Microsoft.Xna.Framework.Game
        {
            Gem diamenty = new Gem();


    Here is the beginning of the class from which I want to call the other one.
  • ADVERTISEMENT
  • #9 8878886
    directx11
    Level 17  
    public Gem(Level level, Vector2 position, bool isPowerUp)
    {
      this.level = level;
      this.basePosition = position;
      ...
    } 


    When you create a Gem object, the constructor will be called (the one at the top). It has parameters you didn't specify in the call:

    Gem diamenty = new Gem();


    You need to specify the objects that the constructor needs when calling, i.e. create an object of the Level, Vector2 and bool classes beforehand and pass them as parameters in the above call.
  • #10 8883202
    andros1245
    Level 11  
    Everything is correct!
    Thank you :)

    One more question:
    I have a class:
    public class Diamenty
        {
            public Diamenty()
            {
            }
            public int diamenciki;
            public int Diament { get { return diamenciki; } set { diamenciki = value; } }
    
            public void Dodaj()
            {
                diamenciki++;
            }
    
        }

    and call it somewhere:
    Diamenty dia = new Diamenty();
    dia.Dodaj();
    

    Unfortunately, after this operation both variables in the class are 0, what's wrong? What am I doing wrong? I will add that if I hard assign a value to the diamond variable, this hard value is displayed, but it still does not want to increment.

    Please help.
  • #11 8883350
    marcinj12
    Level 40  
    The diamond variable should be private, right? There's no point in writing accessors
    public int Diament { get { return diamenciki; } set { diamenciki = value; } } 
    to a public object, since you can now refer directly to the public field diamond...

    Variables after the Add() operation should increment correctly.
    Test this code:
    
    Diamenty dia = new Diamenty();
    dia.Dodaj();
    MessageBox.Show(dia.Diament.ToString());
    dia.Dodaj();
    MessageBox.Show(dia.Diament.ToString());
    dia.Dodaj();
    MessageBox.Show(dia.Diament.ToString());
    


    Aren't you creating a new instance of the Diamond class each time? If you want the class to "keep" the old values, you only need to create the object once:
    Diamenty dia = new Diamenty();
    and then refer to it all the time. Creating a new instance creates a new object, with variables initialized by default (int = 0).
  • #12 8883494
    andros1245
    Level 11  
    In fact, in one file I kept creating this class.

    There is still a problem with incrementing in another file, example:
    I have file A and B, in both I create an instance at the very beginning. In file B I increment the variable but in file A it doesn't see it anymore.

    How to do it?
  • #13 8883529
    marcinj12
    Level 40  
    Example, example, example... :)
    If you're looking for a specific clue, post specific code examples. Paste what you call file A, what you call file B and indicate where the error occurs. There can be a lot of reasons, without a specific code it is impossible to help, you can only "assume".
  • #14 8883789
    andros1245
    Level 11  
    File A with the class:
     public class Diamenty
        {
            public Diamenty()
            {
            }
            public int diamenciki;
    
            public void Dodaj()
            {
                diamenciki++;
            }
    
        }
    
    public class PlatformerGame : Microsoft.Xna.Framework.Game
    {
    Diamenty dia = new Diamenty();
    }
    
    private void DrawHud()
    {
    DrawShadowedString(hudFont, "Diamenty: " + dia.diamenciki.ToString(), hudLocation += new Vector2(0.0f, timeHeight * 1.2f), Color.Yellow);
    }
    }
    


    File B with the increment:
    
    class Gem
    {
    Diamenty dia = new Diamenty();
    
    public void OnCollected(Player collectedBy)
    {
    dia.Dodaj();
    }
    }


    Unfortunately, what has been incremented in B, he does not see in file A :(
  • #15 8883977
    directx11
    Level 17  
    Yes, it won't work. In both files you create two separate objects of the same class, but they are separate "entities", each has its own life. When you increment something in one, the other doesn't see it. There are two solutions to this problem. But both objects will have some common part ("static" type field), or you will pass an object created in one file to another and call its methods there.
  • #16 8884034
    marcinj12
    Level 40  
    As directx11 colleague wrote, you create two independent instances.

    If you want the Gem class to increment an existing Diamond object, you have to pass it to the Gem class, e.g. through the constructor, just like you pass an argument to a function. By default, you pass a reference to a class, so by incrementing in class B you are actually operating on an object from class A.

    Take a look at this simplified example:
    
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
    	public partial class Form1 : Form
    	{
    		public Form1()
    		{
    			InitializeComponent();
    		}
    
    		private void button1_Click(object sender, EventArgs e)
    		{
    			Diamenty dia = new Diamenty();
    
    			dia.Dodaj();   //"zwykłe" zwiększenie
    			MessageBox.Show(dia.diamenciki.ToString());   //tutaj = 1
    
    			Gem gem = new Gem(dia);   //przekazujesz obiekt dia do klasy Gem
    			gem.OnCollected();  //zwiększenie metodą z klasy Gem
    
    			MessageBox.Show(dia.diamenciki.ToString());   //tutaj = 2
    		}
    
    
    	}
    
    	public class Diamenty
        {
            public Diamenty()
            {
            }
    
            public int diamenciki;
    
            public void Dodaj()
            {
                diamenciki++;
            }
    
        }
    
    	class Gem
    	{
    		Diamenty dia;
    		public Gem(Diamenty dia)    //przekazujesz przez konstruktor instancję do klasy dia
    		{
    			this.dia = dia;
    		}
    
    		public void OnCollected()
    		{
    			dia.Dodaj();
    		}
    	}
    }
    
  • #17 8884775
    andros1245
    Level 11  
    marcinj12, you are absolutely right, but this solution is only good for one file :(
    Let's say in file A I will create a diamond instance and then a "relay" instance with a diamond parameter, but it can't be passed to the second file because I would have to create new diamond instances, which is impossible due to no data transfer. I would have to create two variables, which disqualifies the method. The vicious circle closes. I can't just call the methods of the Gem class, because it's an "event". Is there any other way to convey this?

    This method with static - how to execute it?
  • #18 8886165
    marcinj12
    Level 40  
    I assure you that this also works when splitting into two files. It doesn't matter that the Gem class in the example is in the same file - it might as well be in another.
    I am attaching a project (VS 2008) where the Diamond class is in a separate file (FileA), the Gem class is in a separate file (FileB) and there is a form (Form1) illustrating the operation. It all depends on where you instantiate the Diamond class (in the example: only once, in the form constructor). Preview these 3 files in the project.
  • #19 8886437
    andros1245
    Level 11  
    andros1245 wrote:
    I can't just call the methods of the Gem class, because it's an "event".

    As I wrote - I can't move this class, especially since I have no arguments to run it. It's not a problem to add one argument to the class, but the problem is to start it at the right time and with the right arguments, so I have to call it from the second file when there is time and the right argument. I can't do that because if I call an instance in the second file on a new Diamond object it will be a disaster. The general thing is that I can't call the Gem method from the first file.
  • #20 8887628
    marcinj12
    Level 40  
    Okay, I think I understand what you mean.
    So you want to refer to a variable from the Diamond class without passing it to a file ("globally")?

    In that case, you could try using the Singleton pattern, or - to keep it simple - as Colleagues advised, use a simple static class.

    A static class does not have to be initialized, it exists "from the beginning" of the program and can be referenced from anywhere in the program.

    In this case, the Diamond class and its fields and methods would have to be static (no constructor):

    public static class Diamenty
    {
        public static int diamenciki;
    
        public static void Dodaj()
        {
            diamenciki++;
        }
    } 


    And then you can refer to it in any file by writing e.g.
    Diamenty.Dodaj()


    So in the Gem class you would have:
    class Gem
    {
        public void OnCollected(Player collectedBy)
        {
            Diamenty.Dodaj();
        }
    }

Topic summary

The discussion revolves around accessing public functions and variables from different classes within the same namespace in C#. A user seeks guidance on how to utilize methods and variables from one class in another class located in a different file. Responses suggest using static modifiers for direct access or instantiating classes to call methods. The importance of proper constructor usage is emphasized, particularly when passing parameters. The user encounters issues with variable persistence across different files, leading to suggestions of using static classes or the Singleton pattern to maintain shared state. The conversation highlights the necessity of managing object instances correctly to ensure data visibility across classes.
Summary generated by the language model.
ADVERTISEMENT