Question concerning T types - c#

From my question # Possible to make a method with random type? I got this:
public static T GetParameterValue<T>(Parameter source)
{
return (T)source.Value;
}
Now I wonder if it Is also possible to change it in any way so I can set T to the Parameter.Type?
So GetParameterValue(ABoolParameter) where ABoolParameter.Type = bool, ABoolParameter.Value=true
and have it return as a bool with it's value set to true?
and for a string:
GetParameterValue(AStringParameter) where AStringParameter.Type = string, AStringParameter.Value = "somestring"
and have it return as a string with it's value set to "somestring"?
So it should return a bool without me declaring T as a bool before?

Not sure you can do that. And even if you can, it may be a bit confusing for other (more novice) developers to read/maintain the code.
Alternatively, you can use dynamic (or even plain ol' object).

Are you thinking this?
public static void SetParameterValue<T>(this Parameter param, T value)
{
param.Value = value;
param.Type = typeof(T);
}
It depends on what Type on Parameter is. You could create a bunch of if / else statements if it isn't an actual System.Type, but it might not be the most readable thing to do.

Related

Is there a way to create a Pass-By-Reference list of managed-type variables?

edit; Based on responses, I may have been unclear in my final goal. I've updated the last section.
Situation
I have a number of variables which I need to perform the same operation on. In this case, they are strings, and can at the point we reach this code have the value null, "", "Blank", or they could already have an assigned other value that I want to keep.
if (String.IsNullOrEmpty(MyVar1) || "Blank".Equals(MyVar1))
MyVar1 = null;
if(String.IsNullOrEmpty(MyVar2) || "Blank".Equals(MyVar2))
MyVar2 = null;
...
if(String.IsNullOrEmpty(MyVar10) || "Blank".Equals(MyVar10))
MyVar10 = null;
Being a programmer that wants to keep my code clean and this block drives me mad, I'm looking for a way to create a list of these variables, and perform this same if statement + null assignment on each.
For an example, here's what I'd like to do:
MyVar1 = "Blank";
DreamDataStructure varList = new DreamDataStructure() { MyVar1, MyVar2, ..., MyVar10 };
foreach(ref string MyVar in varList)
{
if(String.IsNullOrEmpty(MyVar) || "Blank".Equals(MyVar))
MyVar = null;
}
Console.WriteLine(MyVar1); //Should now be null
What Doesn't Work
1) Because my variables are strings, I can't do something like this.
var myListOfVariables = new[] { &MyVar1, &MyVar2, ..., &MyVar10 };
If I could, I'd be able to foreach over them as expected. Because string is a managed type though, it cannot be passed by reference like this.
2) Similarly, if I just made a List<string> of the variables, they would be passed by value and wouldn't help my case.
3) These variables can't be wrapped in an outer object type, as they need to be used as strings in a large number of places in a legacy application. Assume that it would be too large an effort to change how they're used in every location.
Question
Is there a way to iterate over string (or other managed type) variables in a pass-by-reference way that will allow me to put the entire operation inside of a loop and reduce the duplication of code that's happening here?
The goal here is that I can use the original variables later on in my code with the updated values. MyVar1, etc, are referenced later on already by legacy code which expects them to be null or have an actual value.
If I understand your question correctly, I don't think what you want to do is possible. Please see this question: Interesting "params of ref" feature, any workarounds?
The only thing I can suggest (which I know doesn't answer your question) is creating a method to avoid duplication of your conditional logic:
void Convert(ref string text)
{
if (string.IsNullOrEmpty(text) || "Blank".Equals(text))
{
text = null;
}
}
You could create a function instead of passing references, which would also be more readable.
string Validate(string inputString)
{
return string.IsNullOrEmpty(inputString) || "Blank".Equals(inputString) ? null : inputString;
}
<...>
MyVar1 = Validate(MyVar1);
Update:
Now I get what you're trying to do. You have a bunch of variables, and you want to perform some sort of bulk operation on them without changing anything else. Putting them in a class isn't an option.
In that case you're really stuck operating on them one at a time. There are ways to shorten it, but you're pretty much stuck with the repetition.
I'd
create a string SanitizeString(string input) function
type x = SanitizeString(x); once for each variable
copy and paste the variable names to replace x.
It's lame, but that's about all there is.
Perhaps this would be a better approach. It ensures that the values are always sanitized. Otherwise you can't easily tell whether the values have been sanitized or not:
public class MyValues
{
private string _value1;
private string _value2;
private string _value3;
public string Value1
{
get { return _value1; }
set { _value1 = Sanitize(value); }
}
// repeat for other values
private string Sanitize(string input) =>
string.IsNullOrEmpty(input) || string.Equals("Blank", input) ? null : input;
}
That's one option. Another is to sanitize the inputs earlier. But ideally we want to ensure that a given class is always in a valid state. We wouldn't want to have an instance of a class whether the values may or may not be valid. It's better to ensure that they are always valid.
ref doesn't really factor into it. We don't need to use it often, if ever. With a value type or string we can just return a new value from a function.
If we're passing a reference type and we want to make changes to it (like setting its properties, adding items to a list) then we're already passing a reference and we don't need to specify ref.
I'd try to write methods first without using ref and only use it if you need to. You probably never will because you'll succeed at whatever you're trying to do without using ref.
Your comment mentioned that this is a legacy app and it's preferable not to modify the existing class. That leaves one more option - reflection. Not my favorite, but when you say "legacy app" I feel your pain. In that case you could do this:
public static class StringSanitizer
{
private static Dictionary<Type, IEnumerable<PropertyInfo>> _stringProperties = new Dictionary<Type, IEnumerable<PropertyInfo>>();
public static void SanitizeStringProperties<T>(T input) where T : class
{
if (!_stringProperties.ContainsKey(typeof(T)))
{
_stringProperties.Add(typeof(T), GetStringProperties(typeof(T)));
}
foreach (var property in _stringProperties[typeof(T)])
{
property.SetValue(input, Sanitize((string)property.GetValue(input)));
}
}
private static string Sanitize(string input)
{
return string.IsNullOrEmpty(input) || string.Equals("Blank", input) ? null : input;
}
private static IEnumerable<PropertyInfo> GetStringProperties(Type type)
{
return type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(property => property.PropertyType == typeof(string) && property.CanRead && property.CanWrite);
}
}
This will take an object, find its string properties, and sanitize them. It will store the string properties in a dictionary by type so that once it has discovered the string properties for a given type it won't have to do it again.
StringSanitizer.SanitizeStringProperties(someObject);
you can simply use a string[] and get the changes back to the caller method like this.
public Main()
{
var myVar1 = "Blank";
var myVar2 = "";
string myVar3 = null;
var myVar4 = "";
string[] dreamDataStructure = new string[] { myVar1, myVar2, myVar3, myVar4 };
}
private void ProcessStrings(string[] list)
{
for(int i = 0; i < list.Length; i++)
{
if (String.IsNullOrEmpty(list[i]) || "Blank".Equals(list[i]))
list[i] = null;
}
}

How to use underlying generic types of generics C#

I have an internal generic method byte[] catchAllOperation<T>(T genericItem) and another one byte[] arrayOperation<T>(T[] genericArray). Additionally, I have a highly specialized operation byte[] specializedOperation<TKey,TValue>(CustomMap<Tkey,TValue> customMap).
How to write a method like this? (pseudocode):
public byte[] universalOperation<T>(T anything){
if(T is CustomMap<UKey,UValue>){ // UKey/UValue are unknown
return specializedOperation<UKey,UValue>(anything);
} else if(T is U[]){ // U is unknown
return arrayOperation<U>(anything);
}else{
return catchAllOperation<T>(anything);
}
}
How to get U and how to call arrayOperation<U>(anything); with U if I have only T (and the same for CustomMap<>)? Most questions I have seen assume that U is already known. Serializers use reflection to construct a separate method for each concrete type and then cache the method. But here I only want to redirect/dispatch a universal method to special cases when I could detect these cases.
I will have more types similar to CustomMap, so there is time to make any radical changes to code/approach. All special methods leverage the fact that for blittable underlying types some transformations and custom layout significantly boost the compression ratio of custom types. For custom types I could implement an interface, but for generic arrays it is not an option.
Your question isn't entirely clear to me, but it sounds like you basically need to look in typeof(T) with reflection. Fortunately, dynamic typing in C# means you can get the compiler team to do the hard work - admittedly at execution time:
// Note: all names changed to be more conventional
public byte[] UniversalOperation<T>(T value)
{
dynamic d = value;
return DynamicOperation(d);
}
private byte[] DynamicOperation<UKey, UValue>(CustomMap<UKey, UValue> map)
{
// Do stuff with the map here
}
private byte[] DynamicOperation<U>(U[] array)
{
// Do something with the array here
}
private byte[] DynamicOperation(object value)
{
// Fallback
}
Note that your UniversalOperation method doesn't have to be generic now - it will just use the execution-time type of the value. Of course, that means it may not be quite as you originally intended - for example, if the value is null, you're in trouble - whereas you could have potentially worked with typeof(T) despite that. Without knowing what you're trying to achieve, we can't tell whether or not that's a problem.
Like you are able to read comments it is not possible with generics. The only type is T do getting U and other types is not possible without reflection.
Sample solution:
public static void UniversalOperation<T>(T anything)
{
// check for null etc.
var anythingType = anything.GetType();
if (anythingType.IsGenericType &&
anythingType.GetGenericTypeDefinition() == typeof(CustomMap<,>))
{
var genericArgs = anythingType.GetGenericArguments();
var keyType = genericArgs[0];
var valueType = genericArgs[1];
return specializedOperation(keyValue, valueType, anything);
}
else if (anythingType.IsArray)
{
var elemType = anythingType.GetElementType();
return arrayOperation(elemType, anything);
}
else
{
//T is parameter, so you can pass it
catchAllOperation<T>(anything);
}
}
Unfortunately, solution above required non-generic version of specializedOperation. Anyway, most of serializes (did I understand corretly, you serialize it?) share with non-generic overloads.

C# - better ways to validate if a string is a number other than int.TryParse()?

I find myself often needing to use int.TryParse() to test if a value is an integer. However, when using TryParse, I have to pass a reference variable to the function. So I find myself always needing to create a temp int to be passed in. Usually it looks something like:
int my_temp_integer;
int.TryParse(potential_integer, my_temp_integer);
I find this to be quite cumbersome considering that all I want is a simple true/false response, and I don't care about the actual parsed result. Is there a better way to approach this? Why isn't there an overloaded function where I can just pass the value I want to test and get a true/false response?
Thanks.
you could write an extension method:
public static bool IsInt(this string pString)
{
int value;
return int.TryParse(pString, out value);
}
then your example becomes:
potential_integer.IsInt();
EDIT:
Lately I have been using a generic form of this.
public delegate bool TryParser<T>(string pString, out T pResult);
public static bool Is<T>(this string pString, TryParser<T> pTryParser)
{
T val;
return pTryParser(pString, out val);
}
Can then use it as follows; it's not perfect, but it's more concise than anything I've found:
"1234".Is<int>(int.TryParse); // true
"asdf123".Is<int>(int.TryParse); // false
"1.2345".Is<float>(float.TryParse); // true
"1000".Is<byte>(byte.TryParse); // false
Theoretically, this would also work with custom TryParse methods, as long as you followed the same pattern as the official ones.
Update: If you maintain a static dictionary of TryParse methods by type, you can avoid having to ever directly pass the method. The dictionary can even be populated as needed with reflection.
A simple solution is to create an extension method.
public static class StringExtensions {
public static bool IsInt(this string s) {
int i; return Int.TryParse(s, out i);
}
}
Then you just use it as so:
string s = "123";
if (s.IsInt())
// do something.
if you don't want to actually convert the string, only test it, then you can use Regex
something kinda like this (you may need to adjust this to fit your needs):
public bool IsInt(this string inputData)
{
Regex isNumber = new Regex(#"^\d+$");
Match m = isNumber.Match(inputData);
return m.Success;
}
You could use
bool isInt = str.TrimEnd( new char[] {'0','1','2','3','4','5','6','7','8','9'})
.Length == 0;
A shorter alternative to Muad'Dib above:
bool IsInt(string input)
{
return new System.Text.RegularExpressions.Regex(#"^\d$").IsMatch(input);
}
/Hans

Casting C# out parameters?

Is it possible to cast out param arguments in C#? I have:
Dictionary<string,object> dict; // but I know all values are strings
string key, value;
Roughly speaking (and if I didn't have static typing) I want to do:
dict.TryGetValue(key, out value);
but this obviously won't compile because it "cannot convert from 'out string' to 'out object'".
The workaround I'm using is:
object valueAsObject;
dict.TryGetValue(key, out valueAsObject);
value = (string) valueAsObject;
but that seems rather awkward.
Is there any kind of language feature to let me cast an out param in the method call, so it does this switcheroo for me? I can't figure out any syntax that'll help, and I can't seem to find anything with google.
I don't know if it is a great idea, but you could add a generic extension method:
static bool TryGetTypedValue<TKey, TValue, TActual>(
this IDictionary<TKey, TValue> data,
TKey key,
out TActual value) where TActual : TValue
{
if (data.TryGetValue(key, out TValue tmp))
{
value = (TActual)tmp;
return true;
}
value = default(TActual);
return false;
}
static void Main()
{
Dictionary<string,object> dict
= new Dictionary<string,object>();
dict.Add("abc","def");
string key = "abc", value;
dict.TryGetTypedValue(key, out value);
}
I spy with my little eye an old post that was still active a month ago...
Here's what you do:
public static class DictionaryExtensions
{
public static bool TryGetValueAs<Key, Value, ValueAs>(this IDictionary<Key, Value> dictionary, Key key, out ValueAs valueAs) where ValueAs : Value
{
if(dictionary.TryGetValue(key, out Value value))
{
valueAs = (ValueAs)value;
return true;
}
valueAs = default;
return false;
}
}
And because compilers are great, you can just call it like this:
dict.TryGetValueAs(key, out bool valueAs); // All generic types are filled in implicitely! :D
But say you're not creating a blackboard AI and just need to call this operation the one time. You can simply do a quicksedoodle inliner like this:
var valueAs = dict.TryGetValue(key, out var value) ? (bool)value : default;
I know these answers have been given already, but they must be pretty old because there is no cool hip modern inlining going on to condense these methods to the size we really want: no more than 1 line.
I used Marc's extension method but added a bit to it.
My problem with the original was that in some cases my dictionary would contain an int64 whereas I would expect an int 32. In other cases the dictionary would contain a string (for example "42") while I would like to get it as an int.
There is no way to handle conversion in Marc's method so I added the ability to pass in a delegate to a conversion method:
internal static bool TryGetTypedValue<TKey, TValue, TActual>(
this IDictionary<TKey, TValue> data,
TKey key,
out TActual value, Func<TValue, TActual> converter = null) where TActual : TValue
{
TValue tmp;
if (data.TryGetValue(key, out tmp))
{
if (converter != null)
{
value = converter(tmp);
return true;
}
if (tmp is TActual)
{
value = (TActual) tmp;
return true;
}
value = default(TActual);
return false;
}
value = default(TActual);
return false;
}
Which you can call like this:
int limit;
myParameters.TryGetTypedValue("limitValue", out limit, Convert.ToInt32)
No, there is no way around that. The out parameter must have a variable that matches exactly.
Using a string reference is not safe, as the dictionary can contain other things than strings. However if you had a dictionary of strings and tried to use an object variable in the TryGetValue call, that won't work either even though that would be safe. The variable type has to match exactly.
If you know all values are strings use Dictionary<string, string> instead. The out parameter type is set by the type of the second generic type parameter. Since yours is currently object, it will return an object when retrieving from the dictionary. If you change it to string, it will return strings.
No, you can't. The code inside the method is directly modifying the variable passed to it, it is not passed a copy of the content of the variable.
It is possible by using the Unsafe.As<TFrom, TTo>(ref TFrom source) method to do the cast inline.
var dict = new Dictionary<string, int>
{
["one"] = 1,
["two"] = 2,
["three"] = 3,
};
long result = 0;
dict.TryGetValue("two", out Unsafe.As<long, int>(ref result));
Depending on which platform you are on, this may require you to add a reference to System.Runtime.CompilerServices.Unsafe.

How to determine if a string is a number in C#

I am working on a tool where I need to convert string values to their proper object types. E.g. convert a string like "2008-11-20T16:33:21Z" to a DateTime value. Numeric values like "42" and "42.42" must be converted to an Int32 value and a Double value respectively.
What is the best and most efficient approach to detect if a string is an integer or a number? Are Int32.TryParse or Double.TryParse the way to go?
Int.TryParse and Double.TryParse have the benefit of actually returning the number.
Something like Regex.IsMatch("^\d+$") has the drawback that you still have to parse the string again to get the value out.
In terms of efficiency, yes, TryParse is generally the preferred route.
If you can know (for example, by reflection) the target type in advance - but don't want to have to use a big switch block, you might be interested in using TypeConverter - for example:
DateTime foo = new DateTime(2008, 11, 20);
TypeConverter converter = TypeDescriptor.GetConverter(foo);
string s = converter.ConvertToInvariantString(foo);
object val = converter.ConvertFromInvariantString(s);
I would recommend the .TryParse() personally. That's what I use anyhow. That's if your data is going to be wrong now and again. If you're certain the incoming strings will be able to convert to integers or doubles without a hitch, the .Parse() is faster.
Here's an interesting link to support this.
Keeping the idea of a converter to skip a switch block, you could use the concept of Duck Typing. Basically, you want to turn a string to X, so you make a method that will call X.TryParse(string, out X x) if X has TryParse on it, otherwise you just don't bother (Or I suppose you could throw an error). How would you do this? Reflection and Generics.
Basically you would have a method that would take in a type and use reflection to see if it has TryParse on it. If you find such a method you then call it and return whatever TryParse managed to get. This works well with just about any value type like say Decimal or DateTime.
public static class ConvertFromString
{
public static T? ConvertTo<T>(this String numberToConvert) where T : struct
{
T? returnValue = null;
MethodInfo neededInfo = GetCorrectMethodInfo(typeof(T));
if (neededInfo != null && !numberToConvert.IsNullOrEmpty())
{
T output = default(T);
object[] paramsArray = new object[2] { numberToConvert, output };
returnValue = new T();
object returnedValue = neededInfo.Invoke(returnValue.Value, paramsArray);
if (returnedValue is Boolean && (Boolean)returnedValue)
{
returnValue = (T)paramsArray[1];
}
else
{
returnValue = null;
}
}
return returnValue;
}
}
Where GetCorrectMethodInfo would look something like this:
private static MethodInfo GetCorrectMethodInfo(Type typeToCheck)
{
MethodInfo returnValue = someCache.Get(typeToCheck.FullName);
if(returnValue == null)
{
Type[] paramTypes = new Type[2] { typeof(string), typeToCheck.MakeByRefType() };
returnValue = typeToCheck.GetMethod("TryParse", paramTypes);
if (returnValue != null)
{
CurrentCache.Add(typeToCheck.FullName, returnValue);
}
}
return returnValue;
}
And use would be:
decimal? converted = someString.ConvertTo<decimal>();
I hate plugging myself, but I have this fully explained here:
GetCorrectMethodInfo
Rest of It

Categories