is it possible to have a public method that returns multiple values and then later call that method only retrieving the value that you want?
public static string Values()
{
string length = DAL.Util.getlength();
string Name = DAL.Util.getName(ddlID.SelectedValue);
return length + Name;
}
now I know if I were to call this method just by saying
string a = Values();
it would return the concatenated string of both length and Name, but is there anyway to call just a specific variable from that method even if it were 10 variables long?
Thanks for any advice and help you can provide.
It sounds like you should actually be returning a reference to an object which contains the various different bits of state, instead of returning a single string. Then the caller can decide which bits of state they're really interested in, and retrieve those properties directly.
You could return an object that contains all the values you require.
E.G.
public class MyClass
{
public string Length { get; set; };
public string Name { get; set; };
}
Then you can return this object from your function:
public static MyClass Values()
{
MyClass myClass = new MyClass();
MyClass.Length = DAL.Util.getlength();
MyClass.Name = DAL.Util.getName(ddlID.SelectedValue);
return MyClass;
}
Then you can get whatever properties you require:
MyClass myClass = Values();
string name = myClass.Name;
Sounds like what you actually want is a struct (or a class)
public struct MyStruct
{
public string length
public string name
}
public static MyStruct Values()
{
MyStruct result;
result.name = DAL.Util.getName(ddlID.SelectedValue);
result.length = DAL.Util.getlength();
return (result);
}
Then you can look at the different elements of the struct as you like.
MyStruct data = Values();
Console.WriteLine(data.name);
Console.WriteLine(data.length);
Related
I am trying to find a way to take a class's property and pass it to a method along with another variable to update the property based on conditions. For example
The class
public class MyClass{
public string? Prop1 { get; set; }
public string? Prop2 { get; set; }
public bool? Prop3 { get; set; }
public DateTime? Prop4 { get; set; }
... etc...
}
Test code I would like to get to work...:
var obj = new MyClass();
MyCheckMethod(ref obj.Prop1, someCollection[0,1]);
in the method:
private void MyCheckMethod(ref Object obj, string value)
{
if (!string.isnullorempty(value))
{
// data conversion may be needed here depending on data type of the property
obj = value;
}
}
I want to be able to pass any property of any class and update the property only after validating the value passed in the method. I was hoping I could do this with generics, but I haven't yet found a way to do so. Or if I am over complicating what I need to do.
The problem is that there may be a bit more to the validation of the passed in value than just a simple isnullorempy check.
I also thought about doing something like this:
private void MyCheckMethod(ref object obj, Action action)
Then I could do something like this:
...
MyCheckMethod(ref obj.Prop1, (somecollection[0,1]) => {
... etc....
})
So I am looking for some guidance on how to proceed.
updated info:
The incoming data is all in string format (this is how a 3rd party vendor supplies the data). The data is supplied via API call for the 3rd party product... part of their SDK. However in my class I need to have proper data types. Convert string values to datetime for dates, string values to int for int data types, etc... . The other caveat is that if there isnt a valid value for the data type then the default value of the property should be NULL.
Additional Information:
The incoming data is always in string format.
eg:
I have to update a boolean property.
The incoming value is "". I test to see if the string Value isNullOrEmpty. It is so I dont do anything to property.
The next property datatype is decimal.
The incoming value is "0.343".
I Test to see if the string value is NullorEmpty. It isnt so I can update the property once I do a convert etc.....
Hope this helps.
Thanks
Full solution after edits:
public static class Extensions
{
//create other overloads
public static void MyCheckMethodDate<TObj>(this TObj obj,Expression<Func<TObj,DateTime>> property, string value)
{
obj.MyCheckMethod(property, value, DateTime.Parse);
}
public static void MyCheckMethod<TObj,TProp>(this TObj obj,Expression<Func<TObj,TProp>> property, string value,Func<string, TProp> converter)
{
if(string.IsNullOrEmpty(value))
return;
var propertyInfo = ((MemberExpression)property.Body).Member as PropertyInfo;
if(null != propertyInfo && propertyInfo.CanWrite)
{
propertyInfo.SetValue(obj, converter(value));
}
}
}
public class Obj
{
public object Prop1{get;set;}
public string Prop2{get;set;}
public DateTime Prop3{get;set;}
}
public class Program
{
public static void Main()
{
var obj = new Obj();
obj.MyCheckMethodDate(x=>x.Prop3, "2018-1-1");
Console.WriteLine(obj.Prop3);
}
}
You can pass a lambda expression:
void DoSomething<T>(Expression<Func<T>> property)
{
var propertyInfo = ((MemberExpression)property.Body).Member as PropertyInfo;
if (propertyInfo == null)
{
throw new ArgumentException("The lambda expression 'property' should point to a valid Property");
}else{
var name = ((MemberExpression)property.Body).Member.Name;
var value = property.Compile();
//Do whatever you need to do
}
}
To use:
DoSomething(() => obj.Property1);
You can't pass a reference to an arbitrary property. A property is basically implemented as two methods, set_Property and get_Property, and there's no way to bundle these together.
One option is to have your checker function take delegates to access the property. For example:
private void MyCheckMethod(Func<string> getter, Action<string> setter)
{
var value = getter();
var newValue = value.ToUpper();
setter(value);
}
So now you would say something like this:
public class MyClass
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
var c = new MyClass();
MyCheckMethod(() => c.Prop1, value => c.Prop1 = value);
Use reflection with compiled expressions.
This performs better than reflection and a little bit slower than native code.
It's not type safe, but you can add runtime validation.
I have a static class with several static strings used to store constant values. For example, Foo.Bar might return a string representing database column name and Foo.Foo might return a string with an epoch value.
In my application, I need to concatenate the class name with the name of the string to get the value I need. For example, I know the class name is Foo. I also know the property name is Bar. However the property name changes based on another value. In a foreach, I'm concatenating the class name with the other property name to get a string "Foo.Bar". So far we're okay. When I pass the concatenated string into my method that takes a string, it does not retrieve the static string from the class. In other words, even though the concatenated string is formed correctly as "Foo.Bar", my method does not return the value of Foo.Bar. If I hardcode Foo.Bar I get the string I need but this really needs to be done a runtime.
Any thoughts on how I can fix this? Can I cast this to something?
public static class Foo
{
public static string Bar = "Sample Text";
}
public class Program
{
static void Main()
{
// string "Foo.Bar" is built here by combining two strings.
...
// more processing
...
// I need the literal value of Foo.Bar here not literally "Foo.Bar"...
}
}
If Foo is always the class, then you could just pass in the name of the property instead of the concatenated string:
public string GetString(string propertyName)
{
return typeof(Foo).GetProperty(propertyName).GetValue(null, null);
}
If it's not always Foo, you could pass in the type to the GetString() method also.
Reflection...
Consider:
public class Foo
{
public string Bar { get; set; }
}
You can do:
Foo a = new Foo() { Bar = "Hello!" };
MessageBox.Show(typeof(Foo).GetProperty("Bar").GetValue(a,null) as string);
You need to use reflection. As an aside - note that reflection is slow(er), can lead to errors at runtime, doesn't respond to refactoring tools, etc. so you may want to rethink how you're doing things; eg., a Dictionary<string, string> seems like it'd be easier to manage.
For reflection, you'll need to get (a) the type since it seems you are referincing > 1 class, and then (b) the property. Something like:
var lookupKey = "Foo.Bar";
var typeName = lookupKey.Substring(0, lookupKey.LastIndexOf("."));
var propName = lookupKey.Substring(lookupKey.LastIndexOf(".") + 1);
var typeInfo = Type.GetType(typeName, true);
var propInfo = typeInfo.GetProperty(propName);
return propInfo.GetGetMethod().Invoke(null, null);
I'm trying to convert an object array of my class to a string array.
In this example I have two classes. In one of my classes I want to creat two variables, objects of the other class. On variable will be a array and the other a "regular" variable.
Two classes name. ShowResult and Game.
In the Game class I write:
private ShowResult[] _showResults;
private ShowResult _showResult;
In my properties in my Game class I try to convert this two variables to string array and string:
public string[] ShowResults
{
get { return _showResults.ToString().ToArray(); }
set { _showResults.ToString().ToArray() = value; }
}
public string ShowResult
{
get { return _showResult.ToString(); }
set { _showResult = value; }
}
This doesn't work. I really want my custom object to be converted to string array and to string. But I get an error.. I know I can, but I don't know just how..
If anyone has any suggestion I would be greatful. OBS, this is just an example. But still I don't get why it wont work..?
By the way, sorry for my bad english. ;)
Best regards
Try this:
_showResults.Select(a => a.ToString()).ToArray()
Given the nature of your code (i.e. strings appear to map directly to ShowResults instances), you might want to consider implementing implicit operators:
ShowResults s = "hello";
string ss = s;
Console.WriteLine(ss); // "hello"
class ShowResults
{
public string SomeProp
{
get; private set;
}
public static implicit operator ShowResults(string s)
{
//this is where you'd parse your string
//to form a valid ShowResults
return new ShowResults{SomeProp = s};
}
public static implicit operator string(ShowResults s)
{
return s.SomeProp;
}
}
how can I return more than one type in c# function like I want to return string and datatable ?
The simplest answer is to use the DataTable's TableName property.
The more general answer is to use a Tuple<DataTable, string> or write a class or struct.
use ref or out parameters
ref parameter : requires initilization by the caller method.
public string ReturnName(ref int position)
{
position = 1;
return "Temp"
}
public string GetName()
{
int i =0;
string name = ReturnName(ref i);
// you will get name as Temp and i =1
}
// best use out parameter is the TryGetXXX patternn in various places like (int.TryParse,DateTime.TryParse)
int i ;
bool isValid = int.TryParse("123s",out i);
You can define your own class to use as the return type:
class MyReturnType
{
public string String { get; set; }
public DataTable Table { get; set; }
}
and return an instance of that. You could use a Tuple but it's often better to have meaningful type and property names, especially if someone else is going to be working on the software.
Or you could use an out parameter on the function.
The way you go depends on what is suitable for your situation. If the string and the DataTable are two parts of the same thing a class makes sense. If the string is for an error message when creating the DataTable fails an out parameter might be more appropriate.
Use an out parameter:
public string Function(out DataTable result)
Call it like this:
DataTable table;
string result = Function(out table);
use a tuple as a return.
Is there a way to get a specific element (based in index) from a string array using Property. I prefer using public property in place of making the string array public. I am working on C#.NET 2.0
Regards
Are you possibly trying to protect the original array; do you mean you want a protective wrapper around the array, through "a Property" (not of its own)? I'm taking this shot at guessing the details of your question. Here's a wrapper implementation for a string array. The array cannot be directly access, but only through the wrapper's indexer.
using System;
public class ArrayWrapper {
private string[] _arr;
public ArrayWrapper(string[] arr) { //ctor
_arr = arr;
}
public string this[int i] { //indexer - read only
get {
return _arr[i];
}
}
}
// SAMPLE of using the wrapper
static class Sample_Caller_Code {
static void Main() {
ArrayWrapper wrapper = new ArrayWrapper(new[] { "this", "is", "a", "test" });
string strValue = wrapper[2]; // "a"
Console.Write(strValue);
}
}
If I understand correctly what you are asking, You can use an indexer.
Indexers (C# Programming Guide)
Edit: Now that I've read the others, maybe you can expose a property that returns a copy of the array?
If the property exposes the array:
string s = obj.ArrayProp[index];
If you mean "can I have an indexed property", then no - but you can have a property that is a type with an indexer:
static class Program
{
static void Main()
{
string s = ViaArray.SomeProp[1];
string t = ViaIndexer.SomeProp[1];
}
}
static class ViaArray
{
private static readonly string[] arr = { "abc", "def" };
public static string[] SomeProp { get { return arr; } }
}
static class ViaIndexer
{
private static readonly IndexedType obj = new IndexedType();
public static IndexedType SomeProp { get { return obj; } }
}
class IndexedType
{
private static readonly string[] arr = { "abc", "def" };
public string this[int index]
{
get { return arr[index]; }
}
}
What you need is a Property that can have input (an index).
There is only one property like that, called an Indexer.
Look it up on MSDN.
A shortcut: use a built in code snippet: go to your class and type 'indexer' then press tab twice. Viola!
Properties don't take parameters, so that won't be possible.
You can build a method, for instance
public string GetStringFromIndex(int i)
{
return myStringArray[i];
}
Of course you'll probably want to do some checking in the method, but you get the idea.
I'm assuming that you have a class that has a private string array and you want to be able to get at an element of the array as a property of your class.
public class Foo
{
private string[] bar;
public string FooBar
{
get { return bar.Length > 4 ? bar[4] : null; }
}
}
This seems horribly hacky, though, so I'm either not understanding what you want or there's probably a better way to do what you want, but we'd need to know more information.
Update: If you have the index of the element from somewhere else as you indicate in your comment, you could use an indexer or simply create a method that takes the index and returns the value. I'd reserve the indexer for a class that is itself a container and use the method route otherwise.
public string GetBar( int index )
{
return bar.Length > index ? bar[index] : null;
}
Just return the array from the property; the resulting object will behave as an array, so you can index it.
E.G.:
string s = object.Names[15]
What you're asking can be done, like so:
You can initialize an object that holds your array, giving you exactly what you need:
public class ArrayIndexer<T> {
private T[] myArrRef;
public ArrayIndexer(ref T[] arrRef) {
myArrRef = arrRef;
}
public T this [int index] {
get { return myArrRef[index]; }
}
}
Then, in your class:
public ArrayIndexer arr;
private SomeType[] _arr;
//Constructor:
public MyClass(){
arr = new ArrayIndexer<SomeType>(ref _arr);
}
Usage:
myClassObj.arr[2] // Gives the second item in the array.
Et Voila! An indexed property.