Share via


C# A class property of another class type

Question

Friday, September 12, 2008 9:24 PM

Hi Friends,
I'm a new comer to the C# and oop world.
I have a little problem about the class properties please kindly help me.

I have a class named "User" in namespace_A . (User is not a static class)

Now I'm going to write a class to the namespace_B and I need to assign some value to a User object. so I do the following

using namespace_A;
namespace namespace_B
{
public class MyNewClass
{
//class field
private User _user;

//property
public User UserProperty
{
get{ return _user; }
set{ _user = value;}
}

//A function
public void MyFunction()
{
//Here I need to set a value to the User class UserID Property
//I could do it using the following. it works. but how?
UserProperty.UserID = 1;
// *** why the compiler didn't tell me to create an object first, before
// accessing the properties of the User class.
}

}
}

All replies (11)

Saturday, September 13, 2008 1:17 PM âś…Answered

Let's try again.

    public class UserInsertData  
    {  
        // Unassigned field.  
        // When you attempt to use the field in the DoSomething() method  
        // the compiler will NOT be able to deduce that the field has not  
        // been assigned due to its scope.  
        private NS1.User fieldUser;  
 
        public void DoSomething()  
        {  
            // Unassigned local variable. The scope of this variable  
            // is narrow enough that the compiler will be able to deduce  
            // that you are attempting to use an unassigned variable in  
            // the next step.  
            NS1.User localUser;  
            // Attempting to use the unitialized local variable.  
            // The compiler will give you a warning about this because  
            // it can deduce that the local variable is unassigned.   
            localUser.UserID = 1;  
 
            // Attempting to use the unassigned field.  
            // The compiler will NOT give you a warning about this because  
            // it canNOT deduce that the field has not been initialized.  
            // You WILL get a run time NullReferenceException.  
            fieldUser.UserID = 1;     
        }  
    } 

Quote:
*so here I have set a value to the UserID withour errors.

*Have you executed the code? It will throw a run-time error. There is a difference between the compiler giving you an error and a run-time exception.


Friday, September 12, 2008 9:53 PM

Here is your code:

using namespace_A;  
namespace namespace_B  
{  
    public class MyNewClass  
    {  
        //class field  
        private User _user;  
 
        //property  
        public User UserProperty  
        {  
            get { return _user; }  
            set { _user = value; }  
        }  
 
        //A function  
        public void MyFunction ( )  
        {  
            //Here I need to set a value to the User class UserID Property  
            //I could do it using the following. it works. but how?  
            UserProperty.UserID = 1;  
            // *** why the compiler didn't tell me to create an object first, before  
            // accessing the properties of the User class.  
        }  
    }  

You have only one namespace: namespace_B. namespace_A is referenced but never used. You have only ONE class in namespace_B and that is MyNewClass. You are accessing the property UserProperty of Type User via a Get accessor. Where is the problem?


AlexB


Friday, September 12, 2008 10:21 PM | 1 vote

namespace_A is used in the sample in the fact that this is where the User class is contained.

To answer your question, how is the compiler to know that some other code hasn't assigned a value to your _user field? It cannot be certain that the field hasn't been assigned a value from somewhere else in your code due to the scope of the field.

However, with a local variable where the scope is much tighter, the compiler can deduce that your variable has not been assigned a value - therefore you get a compiler error.

namespace NS1  
{  
    public class User  
    {  
        private int _userID = 0;  
 
        public int UserID  
        {  
            get { return _userID; }  
            set { _userID = value; }  
        }  
    }  
}  
 
namespace NS2  
{  
    public class Class2  
    {  
        private NS1.User _user;  
 
        public NS1.User UserProperty  
        {  
            get { return _user; }  
            set { _user = value; }  
        }  
 
        public void DoSomething()  
        {  
            NS1.User c; // Local variable.  
            c.UserID = 1; // Compiler error.  
 
            // No compiler error because of the scope of the _user field  
            // but you will get a run-time error.  
            UserProperty.UserID = 1;  
        }  
    }  

Friday, September 12, 2008 11:57 PM

 
*To answer your question, how is the compiler to know that some other code hasn't assigned a value to your _user field? It cannot be certain that the field hasn't been assigned a value from somewhere else in your code due to the scope of the field.
*
The compiler does not need to know. It does not care. You will get it in your face at runtime, mind you. If it is not assigned, you will get an exception: Object Reference has a null value.

Incidentally, you've got a property but keep talking about fields.


AlexB


Saturday, September 13, 2008 12:58 AM

AlexBB said:

 
*To answer your question, how is the compiler to know that some other code hasn't assigned a value to your _user field? It cannot be certain that the field hasn't been assigned a value from somewhere else in your code due to the scope of the field.
*
The compiler does not need to know. It does not care. You will get it in your face at runtime, mind you. If it is not assigned, you will get an exception: Object Reference has a null value.

Incidentally, you've got a property but keep talking about fields.


AlexB

namespace NS2     
{     
    public class Class2     
    {     
        private NS1.User _user; // Field     
    
        public NS1.User UserProperty // Property that is irrelevant in the question  
        {     
            get { return _user; }     
            set { _user = value; }     
        }       
    }     
}   
 
namespace NS2     
{     
    public class Class2     
    {     
        private NS1.User fieldUser;
    
        public void DoSomething()     
        {     
            NS1.User localUser;    
            localUser.UserID = 1; // #1 - Compiler cares.    
    
            fieldUser.UserID = 1; // #2 - Compiler doesn't care.    
        }     
    }     
}   
 

That is the question. Why doesn't the compiler complain on #2 even though fieldUser has not been initialized? Yes, it throws a run-time exception as I noted above but the compiler does not complain because the fieldUser field is not a local variable - therefore the compiler cannot deduce if it has been initialized.


Saturday, September 13, 2008 9:10 AM

 Thank you both of you for the replies.

This is my code

I have "User" class in the Electronics.Common Namespace

This is the User Class :

using System;

using System.Collections.Generic;

using System.Text;

namespace Electronics.Common

{

public class User

{

private int _userid;

private string _username;

public int UserID

{

get { return _userid; }

set { _userid = value; }

}

public string UserName

{

get { return _username; }

set { _username = value; }

}

public User()

{

}

}

}

I have "UserInsertData" class in the Electronics.DataAccess Namespace. I have added a assembly reference to the common namespace

using System;

using System.Collections.Generic;

using System.Text;

using Electronics.Common;

namespace Electronics.DataAccess

{

public class UserInsertData

{

private User _user;

public User User

{

get { return _user; }

set { _user = value; }

}

public UserInsertData()

{

}

public void Add()

{

User.UserID = 1;

}

}

}

I could build above solution without errors. Please help me, I'm confused about this.

As far I know,If we want to access a property or function of a class. First We need to create a object of that class using the new operator (if its not static)

But in the UserInsertData class I haven't created a object of "User" type, using the new operator.

I have just used a property of that type.

But the intellisense shows me the properties and functions of the User class.

so here I have set a value to the UserID withour errors.

What is the logic behind this? please help me.


Saturday, September 13, 2008 1:42 PM

Thank you " nmadd" for helping a newcomer like me.  I'm practicing a n-tier architechture book and try to build a my own application according to the tiers describe in that book. I can run it without errors so far. That book doesn't describe codes well. So I have to understand reading those. I'll soon write the class for the business logic layer and a form that access that business logic layer class and post it here. Thank you again you two for helping me. 


Saturday, September 13, 2008 5:48 PM

 Nmadd, I mistakely believed I was answering the OP ojection.


AlexB


Saturday, September 13, 2008 9:26 PM

 nmadd is right. I could run the project because,

the class I created was not involved with any operation. It was just placed in a Library.

According to my understanding.

This is what happens here. Please kindly correct me If I'm wrong anywhere.

This is the running code in my form

this is where the object is created.

User class is placed in my common class library

ProcessAddUser class is placed in the BusinessLogic library

After creating the object in the Form, the code set the objProcessAddUser class's "User" property to the created object.

So the objProcessAddUser class can access the User class's Properties without creating a object.

================================================================

User objUser = new User();

ProcessAddUser objProcessAddUser = new ProcessAddUser();

objUser.FirstName = txt1.Text.Trim();

objUser.LastName = txt2.Text.Trim();

objUser.Address.AddressLine1 = txt3.Text.Trim();

objUser.Address.AddressLine2 = txt4.Text.Trim();

objProcessAddUser.User = objUser;

objProcessAddUser.Invoke();

================================================================

public class ProcessAddUser

{

private User _user;

public User User

{

get { return _user; }

set { _user = value; }

}

public ProcessAddUser()

{

}

public void Invoke()

{

UserInsertData userdata = new UserInsertData();

userdata.UserPr = this.User;

userdata.Add();

this.User.UserID = userdata.UserPr.UserID;

}

}

================================================================

public class User

{

private int _userid;

private string _firstname;

private string _lastname;

private int _addressid;

private Address _address;

public int UserID

{

get { return _userid; }

set { _userid = value; }

}

public string FirstName

{

get { return _firstname; }

set { _firstname = value; }

}

public string LastName

{

get { return _lastname; }

set { _lastname = value; }

}

public int AddressID

{

get { return _addressid; }

set { _addressid = value; }

}

public Address Address

{

get { return _address; }

set { _address = value; }

}

public User()

{

_address = new Address();

}

}

Thank you very much for helping me.

Cheers!

sithira.


Sunday, September 14, 2008 2:27 AM

 Sihara look at what you did. You marked you own post as "answer" although in fact it took you a few days to comprehend the issue. Nmadd in fact did most of the work for you. It is like stealing intelelctual property from an expert on your part:)


AlexB


Sunday, September 14, 2008 6:11 AM

yeah AlexBB. sorry! This time I marked the correct answer. Thanks!