C# property return type

I have a class with two private variables, a string, and a nullable int.

public class ReportParameterHelper
{
   private string _specificAgentIds;
   private int? _specificAgentId;

   // if user selected many Agents in the report filters, parse the array of Agents to a comma-delimited string
   if ( manyAgents )
      _specificAgentIds = string.Join(",", agentArray.Select(x = > x.Id).ToList());
   else
      __specificAgentId = agentArray[0].Id;

   // public property to get the correct Id or Ids
   public T GetAgentIds<T>
   {
      if ( _specificAgentIds != string.empty )
           return _specificAgentIds;
      else
           return __specificAgentId;
   }
}

Obviously this won't work because they are returning two different types, but how do I make something like this work, especially using a property. A property because I want to stay consistent with all the other existing parameters (they are all properties as well).
LVL 8
pzozulkaAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

käµfm³d 👽Commented:
Personally, I say have two different properties. A property is supposed to represent accessing a piece of data. Accessing the same property twice in a row without any other influence on the object itself should result in me receiving the same data from the property. With what you are trying to achieve, I could conceivably receive two different pieces of data--granted, they're the same "data", just different representations. If you simply have two properties, then it's clear how each functions.
pzozulkaAuthor Commented:
Perhaps I wasn't clear. It's actually completely different data, all depends on how the filter parameter was setup. In other words, the filter parameter for the report could allow the user to select a single Agent or the filter could of been setup to allow the user to select up to 100 Agents to filter down the report by.

The end result I'm looking for is for the programmer who will be using my property, to simply say, "objectName.AgentIds". I don't want the user of my class (the programmer) to have to know how the filter parameter was imenented (single vs. multiple agents allowed to be selected). I want my property to be a black box for him. Because all he needs it for is to pass the value returned by the property to a stored procedure.
Dustin HopkinsSenior Web DeveloperCommented:
If it's just going to be passed to a stored procedure anyways and the programmer isn't supposed to know(or care?) what it contains, then why not just make the property a string instead of a nullable int?

Personally though, I would think that the class should have separate functions i.e. GetAgentId and GetAgentIds that would do the conversion on the underlying property.

Hope this helps,
Dustin

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Introduction to R

R is considered the predominant language for data scientist and statisticians. Learn how to use R for your own data science projects.

anarki_jimbelSenior DeveloperCommented:
One way is to return an array (or, better, a list of nullable int IDs. And it is up to a consumer of a method to check how many IDs are returned. If a list contains just one item - specificAgentId = listOfIDs[0].
If the list is empty - nothing was found.

Something like that...
käµfm³d 👽Commented:
I still maintain my previous assertion:  a property is for data access, not coding magic. A property called "GetXXXX" is redundant in name, and does not follow commonly accepted coding standards. Furthermore, having a property which can vary in type is just not practical. Either my agent ID is a string, or it is an integer... it can't be both at the same time. If I as the consumer of your class need the type to be something different, then I'll take care of changing the representation as I need it.
pzozulkaAuthor Commented:
Dustin, the reason I can't pass a string to the sproc regardless if it's a single Id or many Ids, is because the sproc is configured depending on the report filter parameter. If the filter was configured to only allow a user to select a single Agent, the sproc will be expecting an int to be passed. If the filter allows for many, then a different sproc is called which expects a string to be passed (I.e. "6373,3847,8373,7234"). The sproc expecting the sting of comma separated IDs is slower because it calls a function to create a temp table to convert the string into a single column table. This is obviously less efficient.

anarki_jimbel, the reason I don't want the programmer to consume is because all of this code is boiler plate code. We have 1000 reports, and all of them are pretty much doing the same thing, setting up the filters, then collecting user input from the filters, and then passing them to the sprocs. Thus we are creating a black box framework, to just call methods to add filters, and then call black box properties to collect the user input. Thus don't want the programmer to consume anything, otherwise it will be more code repetition for all future reports. Repetitive code = bad code.
pzozulkaAuthor Commented:
Good point. I was hoping to avoid having to properties that do almost the same thing. But it doesn't look like I have other options.
anarki_jimbelSenior DeveloperCommented:
In any case, properties are used by programmers, but I'm not going to delve into a philosophical discussions :).

Still can't really understand your problems. Make both properties to return "string". Single ID can be also a string. Otherwise it will be a mess.
it_saigeDeveloperCommented:
Another avenue you could take is to implement a class that represents the AgentID's as a collection; e.g. -
class AgentIDs : List<string>
{
	public AgentIDs() : base() { ;}

	public AgentIDs(IEnumerable<string> source) : base(source) { ;}

	public AgentIDs(string source, string delimeter = ",") : base(source.Split(new [] { delimeter }, StringSplitOptions.RemoveEmptyEntries)) { ;}

	public void Add(string item, string delimeter = ",")
	{
		if (item.Contains(delimeter))
			base.AddRange(item.Split(new[] { delimeter }, StringSplitOptions.RemoveEmptyEntries));
		else
			base.Add(item);
	}

	public override string ToString()
	{
		return ToString(",");
	}

	public string ToString(string delimeter = ",")
	{
		return string.Join(delimeter, base.ToArray());
	}
}

Open in new window

In this way you could:
      1.  Add individual or groups of items using the Add method.
      2.  Add a range of items using the AddRange method.
      3.  Retrieve a specified agent id by index using standard linq methods.
      4.  Get the expected parameterized list output by simply calling the ToString method (or using the object itself in a string implied scenario; e.g. -
string.Format("{0}", ReportParameterHelper.AgentIDs)

Open in new window


Proof of concept -
using System;
using System.Collections.Generic;
using System.Linq;

namespace EE_Q28766880
{
	class Program
	{
		static void Main(string[] args)
		{
			AgentIDs agents = new AgentIDs();
			agents.Add("12340,12341,12342,12343,12344,12345,12346,12347,12348,12349");
			Console.WriteLine(agents);
			agents.Add("Peter");
			Console.WriteLine(agents);
			var peter = agents.FirstOrDefault(x => x.Equals("peter", StringComparison.OrdinalIgnoreCase));
			Console.WriteLine(peter);
			Console.ReadLine();
		}
	}

	class AgentIDs : List<string>
	{
		public AgentIDs() : base() { ;}

		public AgentIDs(IEnumerable<string> source) : base(source) { ;}

		public AgentIDs(string source, string delimeter = ",") : base(source.Split(new [] { delimeter }, StringSplitOptions.RemoveEmptyEntries)) { ;}

		public void Add(string item, string delimeter = ",")
		{
			if (item.Contains(delimeter))
				base.AddRange(item.Split(new[] { delimeter }, StringSplitOptions.RemoveEmptyEntries));
			else
				base.Add(item);
		}

		public override string ToString()
		{
			return ToString(",");
		}

		public string ToString(string delimeter = ",")
		{
			return string.Join(delimeter, base.ToArray());
		}
	}
}

Open in new window

Which produces the following output -Capture.JPG-saige-
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.