可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I want to give a parameter to a method and i want my method to return data by looking the parameter. Data can be in type of boolean, string, int or etc. How can i return a variable type from a method? I don't want to return an object type and then cast it to another type. For example:
BlaBla VariableReturnExampleMethod(int a)
{
if (a == 1)
return "Demo";
else if (a == 2)
return 2;
else if (a == 3)
return True;
else
return null;
}
The reason why i want that is i have a method that reads a selected column of a row from the database. Types of columns are not same but i have to return every column's information.
回答1:
How can i return a variable type from a method? I don't want to return an object type and then cast it to another type.
Well that's basically what you do have to do. Alternatively, if you're using C# 4 you could make the return type dynamic
, which will allow the conversion to be implicit:
dynamic VariableReturnExampleMethod(int a)
{
// Body as per question
}
...
// Fine...
int x = VariableReturnExampleMethod(2);
// This will throw an exception at execution time
int y = VariableReturnExampleMethod(1);
Fundamentally, you specify types to let the compiler know what to expect. How can that work if the type is only known at execution time? The reason the dynamic
version works is that it basically tells the compiler to defer its normal work until execution time - so you lose the normal safety which would let the second example fail at compile time.
回答2:
Use dynamic
Keyword in place of BlahBlah
if you are targeting .Net 4.0
but if lesser one then object
is your safest bet because it is the base class for every other class you can think of.
回答3:
It sounds like this might be a good case for generics. If you know what data type you're expecting when you call it, you can call that particular generic version of the function.
回答4:
Consider using something like Dapper-dot-net (written by Marc Gravell and Sam Saffron at our very own Stack Overflow) to pull things out of the DB. It handles the database to object mapping for you.
Furthermore, if you don't want to use a tool, and you're pulling from a Database, and you know the data types of the various columns at compile time (like it sounds you do), you should probably be working row-by-row rather than column-by-column.
//Pseudo-code:
List<DatabaseObject> objects = new List<DatabaseObject>();
foreach(var row in DatabaseRows)
{
var toAdd = new DatabaseObject();
toAdd.StringTypeVariable = "Demo";
toAdd.IntTypeVariable = 2;
toAdd.BoolTypeVariable = true;
object.Add(toAdd);
}
Note: you could use object initializer syntax, and linq here but this is the most basic way I could think of demoing this without using a ton of extra stuff.
Also note, that here I'm assuming that you don't actually want to return "Demo", 2, and true, but values that use the row. That just means you'd change the hard coded values to: row.GetStringType(stringColumnIdx)
or something similar.
回答5:
Use return type as object
, then you are able to get any return type. you have to handle the return type ether through reflection or other method.
check this:
void Main()
{
object aa = VariableReturnExampleMethod(3);
Console.WriteLine(aa.ToString());
}
object VariableReturnExampleMethod(int a)
{
if (a == 1)
return "Demo";
else if (a == 2)
return 2;
else if (a == 3)
return true;
else
return null;
}
Edit:
I am in the favor of strongly typed objects and you can implement it easily on .net platform.
if(returnedValue !=null)
{
string currentDataType = returnedValue.GetType().Name;
object valueObj = GetValueByValidating(currentDataType, stringValue);
}
public object GetValueByValidating(string strCurrentDatatype, object valueObj)
{
if (valueObj != "")
{
if (strCurrentDatatype.ToLower().Contains("int"))
{
valueObj = Convert.ToInt32(valueObj);
}
else if (strCurrentDatatype.ToLower().Contains("decimal"))
{
valueObj = Convert.ToDecimal(valueObj);
}
else if (strCurrentDatatype.ToLower().Contains("double") || strCurrentDatatype.ToLower().Contains("real"))
{
valueObj = Convert.ToDouble(valueObj);
}
else if (strCurrentDatatype.ToLower().Contains("string"))
{
valueObj = Convert.ToString(valueObj);
}
else
{
valueObj = valueObj.ToString();
}
}
else
{
valueObj = null;
}
return valueObj;
}
回答6:
I look on your asks and one is better than second, but last i must rewritting to better understand solution. And this solution skiped long if else stack and replacing it by foreach on Types enum, where we can implement all types what we need. I more like using dynamic, but this is usable too.
Main function GetValueByValidating
returned value if is type defined and possible, in other cases return false
Look niranjan-kala this is your main function after rewriting.
///
/// Enum of wanted types
///
public enum Types
{
[ExtendetFlags("int")]
INT,
[ExtendetFlags("decimal")]
DECIMAL,
[ExtendetFlags("double")]
DOUBLE,
[ExtendetFlags("real")]
REAL,
[ExtendetFlags("string")]
STRING,
[ExtendetFlags("object")]
OBJECT,
[ExtendetFlags("null")]
NULLABLE
}
///
/// Cycle by types when in enum exist string reference on type (helper)
///
///
///
public static Types GetCurrentType(string container)
{
foreach (Types t in Enum.GetValues(typeof(Types)))
{
if (container.Contains(t.GetFlagValue()))
{
return t;
}
}
return Types.NULLABLE;
}
///
/// Return object converted to type
///
///
///
///
public static object GetValueByValidating(string strCurrentDatatype, object valueObj)
{
var _value = valueObj != null ? valueObj : null;
try
{
Types _current = _value != null ? GetCurrentType(strCurrentDatatype.ToLower()) : Types.NULLABLE;
switch (_current)
{
case Types.INT:
valueObj = Convert.ToInt32(valueObj);
break;
case Types.DECIMAL:
valueObj = Convert.ToDecimal(valueObj);
break;
case Types.DOUBLE:
valueObj = Convert.ToDouble(valueObj);
break;
case Types.REAL:
valueObj = Convert.ToDouble(valueObj);
break;
case Types.STRING:
valueObj = Convert.ToString(valueObj);
break;
case Types.OBJECT:
break;
case Types.NULLABLE:
throw new InvalidCastException("Type not handled before selecting, function crashed by retype var.");
}
} catch (InvalidCastException ex)
{
Log.WriteException(ex);
valueObj = false;
}
return valueObj;
}