Expression.Default in .NET 3.5 - linq

How can I emulate Expression.Default (new in .NET 4.0) in 3.5?
Do I need to manually check the expression type and use different code for reference and value types?
This is what I'm currently doing, is there a better way?
Expression GetDefaultExpression(Type type)
{
if (type.IsValueType)
return Expression.New(type);
return Expression.Constant(null, type);
}

The way you did it is good. There is no Type.GetDefaultValue() method built in to the .NET Framework as one would expect, so the special case handling for value types is indeed necessary.
It is also possible to produce a constant expression for value types:
Expression GetDefaultExpression(Type type)
{
if (type.IsValueType)
return Expression.Constant(Activator.CreateInstance(type), type);
return Expression.Constant(null, type);
}
The advantage of this I suppose would be that the value type is only instanciated once, when the expression tree is first built, rather than every time the expression is evaluated. But this is nitpicking.

How about using an extension method?
using System;
using System.Linq.Expressions;
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
Type t = typeof(int);
Expression e = t.Default(); // <-----
Console.WriteLine(e);
t = typeof(String);
e = t.Default(); // <-----
Console.WriteLine(e);
Console.ReadLine();
}
}
public static class MyExtensions
{
public static Expression Default(this Type type)
{
if (type.IsValueType)
return Expression.New(type);
return Expression.Constant(null, type);
}
}
}

Related

How to check record in c# 9 in NET 5 is immutable at runtime

Record is a new feature in c#9, Net 5
It's said
If you want the whole object to be immutable and behave like a value, then you should consider declaring it as a record
Creating a record in c#9 , NET 5:
public record Rectangle
{
public int Width { get; init; }
public int Height { get; init; }
}
Then instantiating it:
var rectangle = new Rectangle (20,30);
Trying to change the value:
rectange.Width=50; //compiler error
Compiler raise the error:
error CS8852: Init-only property or indexer 'Rectangle.Width' can only be assigned in an object initializer, or on 'this' or 'base' in an instance constructor or an 'init' accessor.
That is right and insure that the record is immutable.
Using a method like to test IsImmutable type give false, because in record there is no generated readonly properties.
How to check the record in c# 9, Net 5 is immutable at runtime or even it has init property?
A record is indeed mutable at runtime. This is intentional, is it means most serializer frameworks work without updating.
It is however possible to check if a property is initonly by checking:
public static bool IsInitOnly(PropertyInfo propertyInfo)
{
return propertyInfo?.SetMethod.ReturnParameter
.GetRequiredCustomModifiers()
.Any(x => x.FullName == _isExternalInitName)
?? false;
}
private static string _isExternalInitName =
typeof(System.Runtime.CompilerServices.IsExternalInit).FullName;
I don't think that it's possible to check for immutability at runtime.
Here's some of the generated code for your record. You can see that both properties have a public setter.
public class Rectangle : IEquatable<Rectangle>
{
[CompilerGenerated]
private readonly int <Width>k__BackingField;
[CompilerGenerated]
private readonly int <Height>k__BackingField;
protected virtual Type EqualityContract
{
[CompilerGenerated]
get
{
return typeof(Rectangle);
}
}
public int Width
{
[CompilerGenerated]
get
{
return <Width>k__BackingField;
}
[CompilerGenerated]
set
{
<Width>k__BackingField = value;
}
}
public int Height
{
[CompilerGenerated]
get
{
return <Height>k__BackingField;
}
[CompilerGenerated]
set
{
<Height>k__BackingField = value;
}
}
The following code will compile and run without errors.
var rect = new Rectangle { Height = 1, Width = 2 };
typeof(Rectangle).GetProperty("Height").SetValue(rect, 5);
Console.Write(rect.Height);
//Prints 5
At runtime the init accessor is just a regular setter. It's only at compile time that a check is made to only allow init accessor to be called during object initialization.
So I don't see any way to check at runtime that Rectangle is immutable.

Code lens not showing correct number of tests

In the VS 2013, I see number of unit tests for a method.
It works fine if I am calling the method directly from the TestMethod, but if I call sut from a helper/private method, the codelens does not seem to count that test.
I am using private method to pass different parameters to my test method and execute the test. I know I can use xls, csv or db to do that but I just want to do that in the code and make the test count.
Is there a way to make codelens count tests in this scenario?
MyClass.cs
--1/1 passing ( this is fine)
public bool MyMethbod (bool input)
{
return input
}
MyClassTest.cs
[TestMethod]
public void MyMethod_ShuoldReturnTrue
{
var returnValue = new MyClass().MyMethod(true);
Assert.IsTrue(returnValue)
}
MyClass.cs
--0/0 passing ( I am expecting codelens to show 1/1)
public bool MyMethbod (bool input)
{
return input;
}
MyClassTest.cs
[TestMethod]
public void MyMethod_ShuoldReturnTrue
{
MyMethod_ShuoldReturnTrue_Refactored(true);
}
private void MyMethod_ShuoldReturnTrue_Refactored(bool someValue)
{
var returnValue = new MyClass().MyMethod(someValue);
Assert.AreEqual(returnValue, someValue);
}

Extension method with generic Func parameter of other type

Is there a way to implement an extension method to a generic type that takes in arguments a Func of another type?
For exemple, a usage something similar to this:
myFirstObject.Extension<myOtherObject>( other => other.Prop );
Or with a more complicated Func:
myFirstObject.Extension<myOtherObject>( other => other.Prop > 2 && other.Prop < 15 );
I found some related question like this one, but in my case, I need generic types inside the extension method too.
Here's what I came up with:
public static bool Extension<TSource, TIn, TKey>(this TSource p_Value, Expression<Func<TIn, TKey>> p_OutExpression)
{ return true; }
However, when I try to use it, it does not take into consideration the second type.
Am I missing something?
Look at this:
s => s.Length;
How's the compiler suppose to know whether or not s is a string or s is an array or some other type that has a Length property? It can't, unless you give it some information:
(string s) => s.Length;
Oh, there we go. So now, try this:
myFirstObject.Extension((myOtherObject o) => o.Prop > 2 && o.Prop < 15);
That will work, because you've told the compiler what it should use for TIn, and it can figure out what to use for TKey based on the expression.
I found that another solution would be to create another method that takes in argument a type.
For instance:
Void Extension(Type p_Type, [THE TYPE] p_Params)
{
MethodInfo realExtensionMethod = typeof([CLASS CONTAINING THE METHOD]).GetMethod("RealExtension");
realExtensionMethod = realExtensionMethod.MakeGenericMethod(p_Type);
realExtensionMethod.Invoke(null, new object[] {p_Type, p_Params });
}
Void RealExtension<TYPE>(params)
{
}
Then at usage time:
Type objectType = typeof(myOtherObject);
myFirstObject.Extension(objectType, other => other.Prop );
When you call a generic method in C# you can explicitly declare all of the generic type parameters or you can have them all inferred, but you cannot have some explicitly declared and some inferred.
So, if I had this method:
public void Foo<X, Y>(X x, Y y)
{
/* Do somethhing */
}
Then here's what works and what doesn't:
int a = 42;
string b = "Hello, World!";
// Legal
Foo(a, b);
Foo<int, string>(a, b);
//Illegal
Foo<int>(a, b);
The best you can do is move the first generic parameter up to the class level, but not it won't work as an extension method. Nevertheless you may like this approach.
public static class Class<TSource>
{
public static bool Method<TIn, TKey>(
TSource p_Value,
Expression<Func<TIn, TKey>> p_OutExpression)
{
return true;
}
}
Now you can call it like this:
Expression<Func<long, decimal>> f =
l => (decimal)l;
var result = Class<int>.Method(a, f);
But as I say, it won't work as an extension method now.

JFace TreeView not launching when Input is a String

I'm trying launch a simple JFace Tree.
It's acting really strange however. When I setInput() to be a single String, the tree opens up completely blank. However, when I set input to be a String array, it works great.
This has nothing to do with the LabelProvider or ContentProvider since these behave the same no matter what (it's a really simple experimental program).
setInput() is officially allowed to take any Object. I am confused why it will not take a String, and knowing why may help me solve my other problems in life.
Setting a single String as input:
TreeViewer treeViewerLeft = new TreeViewer(shell, SWT.SINGLE);
treeViewerLeft.setLabelProvider(new TestLabelProvider());
treeViewerLeft.setContentProvider(new TestCompareContentProvider());
treeViewerLeft.expandAll();
treeViewerLeft.setInput(new String("Stooge"));
Setting an array of Strings:
TreeViewer treeViewerLeft = new TreeViewer(shell, SWT.SINGLE);
treeViewerLeft.setLabelProvider(new TestLabelProvider());
treeViewerLeft.setContentProvider(new TestCompareContentProvider());
treeViewerLeft.expandAll();
treeViewerLeft.setInput(new String[]{"Moe", "Larry", "Curly"});
The second works, and launches a tree using the following providers:
public class TestCompareContentProvider extends ArrayContentProvider implements ITreeContentProvider {
public static int children = 0;
public Object[] getChildren(Object parentElement) {
children++;
if (children > 20){
return null;
}
return new String[] {"Moe", "Larry", "Curly"};
}
public Object getParent(Object element) {
return "Parent";
}
public boolean hasChildren(Object element) {
if (children >20){
return false;
}
return true;
}
}
and
public class TestLabelProvider extends LabelProvider {
public String getText(Object element){
return "I'm something";
}
public Image getImage(Object element){
return null;
}
}
You've inherited getElements from the ArrayContentProvider and that only works with arrays. You should override this method.
I don't think you need to extend ArrayContentProvider at all.

How To write TestCase nunit test for keyPairValue

I am looking for a way to pass keyValuePair into my test with TestCase
[TestCase<KeyValuePair<int,string>>(1,"XX")]
public void someTest(KeyValuePair<int,string> expectedkeyValuePairs)
{
// do some thing;
}
The answer is
[TestCase(1,"XXX")]
public void someTest(int key,string value)
{
var expectedkeyValuePairs = new KeyValuePair<int, string>(key, value);
// do some thing;
}
Simply use two separate parameters: One for key, one for value. And then create the KeyValuePair from them within your test.

Resources