Creating a generic Array2D wrapper class - c#

For the sake of more easily switching between different data structures I'd like to create a generic wrapper class for a 2D array...
public sealed class Array2D<T>
{
private T<,> _fields;
public Array2D()
{
}
}
private T<,> _fields; is giving me the error:
The type parameter 'T' cannot be used with type arguments
I'm having a hard time understanding C# generics in this case. How would I be able to solve this?

<,> is for referencing unbound generic types. What you are looking for is [,]:
public sealed class Array2D<T>
{
private T[,] _fields;
public Array2D()
{
}
}

to declare array you need to use [] so it should be
T[,] array;

Try List<List<SomeType>> for two dim array. May be List<List<T>> in your case. This would be generic as well. And add the using statements using System.Linq; using System.Linq.Expressions; You can get very rich functionality as well.

Multidimensional Arrays is like this:
private T[,] _fields;
So you should:
public sealed class Array2D<T>
{
private T[,] _fields;
//Or as property
public T[,] Fields
{
get { return _fields; }
set { _fields = value; }
}
public Array2D()
{
}
}
Then to use it:
Array2D<int> arr = new Array2D<int> {Fields = new[,] {{1, 2}, {3, 4}, {5, 6}, {7, 8}}};

Related

Restrict an IList<T> extension method to exclude Arrays

Supposing I create an extension method for IList but this extension is part of a library potentially used across many projects. I do not have the control on how it is called.
Is there a way to prevent an Array to call an IList<T> extension method at compile time? This to avoid any misuse, the caller cannot guess the exact implementation, if the .Add() method would be called or only the indexer for example.
I could not find a possible solution with generic constraint type.
So far the only possibility left would be to restrict the extension method to List<T> directly.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var array = new[]{"Hello"};
array.DummyInsert("World"); // this will crash at run time
}
}
public static class DummyExtension
{
public static T DummyInsert<T>(this IList<T> list, T insertValue)
{
list.Add(insertValue);
return insertValue;
}
}
You can add your extension method to List<T> not on IList<T>
I Agree with Ed Plunkett, use a ReadOnlyCollection<T>. But you can do it like this. It's your foot, you can shoot it if you want.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var array = new[]{"Hello"};
var world = array.Insert("World"); // this will crash at run time
Console.WriteLine(array.Length);
}
}
public static class DummyExtension
{
public static T Insert<T>(this IList<T> list, T insertValue)
{
Console.WriteLine("WrongInsert");
list.Add(insertValue);
return insertValue;
}
[Obsolete("If want a compile time exception you can do this too.", true)]
public static T Insert<T>(this T[] list, T insertValue)
{
Console.WriteLine("RightInsert");
return insertValue;
}
}
This prints
RightInsert
1
https://dotnetfiddle.net/i6p1Z5
EDIT:
It was pointed out in the comments below that this won't work if your array has been cast to an IList<T> either explicitly or implicitly. There is nothing wrong with using List<T> here instead of IList<T> unless you are trying to actually extend the IList<T>. In that case extend it in a way that makes sense for all IList<T>. I just wanted to show that yes, what you ask can be done. With great power comes great responsibility.
The run-time issue is because of the fact that the Array is of fixed length hence when you try to insert an element into it you end up with an exception. Instead you can have your own extension method for case Array and handle the insertion accordingly.
public class Program
{
public static void Main()
{
var array = new[] { "Hello" };
array = array.Insert("World");
}
}
public static class DummyExtension
{
public static T Insert<T>(this IList<T> list, T insertValue)
{
list.Add(insertValue);
return insertValue;
}
public static T[] Insert<T>(this T[] list, T insertValue)
{
var destArray = new T[list.Length + 1];
Array.Copy(list, destArray, list.Length);
destArray[destArray.Length - 1] = insertValue;
return destArray;
}
}
Well I agree it may be a crude way, but it will work for your case.

My array class in C#

I'm trying to do this with Dictionary, Array seems more general so I'm using it as an example.
Class MyArray
{
private Array array;
public Array [p] // a property
{
get {return array[p]};
set
{
array[p] = value;
more_stuff();
}
}
}
This is sudo-code. I've included only a part of the class, where my problem would be. Can I use a property as above, or another structure to achieve this?
(new MyArray[]{4, 3, 1, 5})[2] = 4;
You're looking for an indexer.
So you're class should look like this:
class MyArray<T>
{
private T[] array = new T[100];
public T this[int p]
{
get
{
return array[p];
}
set
{
array[p] = value;
// more_stuff();
}
}
}
To be able to use a collection initializer (e.g. new MyArray<int>{4, 3, 1, 5}), your class has to implement IEnumerable and provide a Add method.

Create class based up on abstract type

I have selveral classes based upon a standard abstract class and they will be loaded from a datatable (for the sample I used an array of int). The class wil be intiated by type and then load the specific details for that class. Currenlty I am doing this with a switch statement but is it possbile to do this an other way?
class Program
{
static void Main(string[] args)
{
var list = new[] {1, 1, 3, 2, 2, 4};
TypeBase typeClass = null;
foreach (var i in list)
{
switch (i)
{
case 1:
{
typeClass = new Type1();
break;
}
case 2:
{
typeClass = new Type2();
break;
}
case 3:
{
typeClass = new Type3();
break;
}
}
}
if (typeClass != null)
{
typeClass.LoadDetails();
}
}
}
public class TypeBase
{
public int Type { get; set; }
public virtual void LoadDetails()
{
throw new NotImplementedException();
}
}
public class Type1 : TypeBase
{
public override void LoadDetails()
{
// Load type Specific details
}
}
public class Type2 : TypeBase
{
public override void LoadDetails()
{
// Load type Specific details
}
}
public class Type3 : TypeBase
{
public override void LoadDetails()
{
// Load type Specific details
}
}
There are several solutions.
1. Create types with reflection
This solution has already been given by Nair. Since I expect your types will not be called Type1, Type2, etc. I assume this will not work for you.
2. Store types in a dictionaries with types
Create a dictionary which will replace your switch/case. It contains the types you need to create:
Dictionary<int, Type> types = new Dictionary<int, Type>
{
{1, typeof(Type1)},
{2, typeof(Type2)},
{3, typeof(Type3)}
};
use this to create your types:
Type type;
if (types.TryGetValue(i, out type))
{
TypeBase typeClass = (TypeBase)Activator.CreateInstance(type);
typeClass.LoadDetails();
}
This solution is faster than solution #1, since only one "reflection" operation is used.
3. Store types in a dictionaries with factory methods
Create a dictionary which will replace your switch/case. It will contain factory methods:
Dictionary<int, Func<TypeBase>> factories = new Dictionary<int, Func<TypeBase>>
{
{1, () => new Type1()},
{2, () => new Type2()},
{3, () => new Type3()}
};
use this to create your types:
Func<TypeBase> factory;
if (factories.TryGetValue(i, out factory))
{
TypeBase typeClass = factory();
typeClass.LoadDetails();
}
This solution is faster than solution #2, since there is not reflection used.
4. Store types in a dictionaries with instances
Create a dictionary which will replace your switch/case. It will contain instances of your types. This solution will only work if these instances are immutable and will not change state during calls.
Dictionary<int, TypeBase> typeClasses = new Dictionary<int, TypeBase>
{
{1, new Type1()},
{2, new Type2()},
{3, new Type3()}
};
use this to create your types:
TypeBase typeClass;
if (baseClasses.TryGetValue(i, out baseClass))
{
typeClass.LoadDetails();
}
This solution is faster than solution #3, since no instances are created with every call.
Some side notes
Why not use an interface, with one member LoadDetails? In your example member Type is never used.
Why not make TypeBase.LoadDetails an abstract method?
If your keys are always of type Int32 and are in a continuous range, you could consider using a List<T> or even an array, which will be faster than a dictionary.
Ideally, you should follow factory method to such requirement. Else, if you are happy to follow conventions for your subclass then a cheap trick would be something like below.
using System;
using System.Runtime.Remoting;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
var list = new[] {1, 1, 3, 2, 2, 4};
TypeBase typeClass = null;
foreach (var i in list)
{
ObjectHandle handle = Activator.CreateInstanceFrom("ConsoleApplication1", string.Format("{0}{1}", "Type", i));//Program- Name of the assembl
var typeBase = (TypeBase) handle.Unwrap();
typeBase.Type = i;
typeClass.LoadDetails();
}
}
}
public class TypeBase
{
public int Type { get; set; }
public virtual void LoadDetails()
{
throw new NotImplementedException();
}
}
public class Type1 : TypeBase
{
public override void LoadDetails()
{
// Load type Specific details
}
}
}
Note : I personally won't follow such approach and would more pleased with factory methods or fair number of switches. This is just to flash a possibility only. Please test and amend accordingly (if decide to follow)

Using Property to get array element in C#

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.

Can I initialize a C# attribute with an array or other variable number of arguments?

Is it possible to create an attribute that can be initialized with a variable number of arguments?
For example:
[MyCustomAttribute(new int[3,4,5])] // this doesn't work
public MyClass ...
Attributes will take an array. Though if you control the attribute, you can also use params instead (which is nicer to consumers, IMO):
class MyCustomAttribute : Attribute {
public int[] Values { get; set; }
public MyCustomAttribute(params int[] values) {
this.Values = values;
}
}
[MyCustomAttribute(3, 4, 5)]
class MyClass { }
Your syntax for array creation just happens to be off:
class MyCustomAttribute : Attribute {
public int[] Values { get; set; }
public MyCustomAttribute(int[] values) {
this.Values = values;
}
}
[MyCustomAttribute(new int[] { 3, 4, 5 })]
class MyClass { }
You can do it, but it isn't CLS compliant:
[assembly: CLSCompliant(true)]
class Foo : Attribute
{
public Foo(string[] vals) { }
}
[Foo(new string[] {"abc","def"})]
static void Bar() {}
Shows:
Warning 1 Arrays as attribute arguments is not CLS-compliant
For regular reflection usage, it may be preferable to have multiple attributes, i.e.
[Foo("abc"), Foo("def")]
However, this won't work with TypeDescriptor/PropertyDescriptor, where only a single instance of any attribute is supported (either the first or last wins, I can't recall which).
Try declaring the constructor like this:
public class MyCustomAttribute : Attribute
{
public MyCustomAttribute(params int[] t)
{
}
}
Then you can use it like:
[MyCustomAttribute(3, 4, 5)]
That should be okay. From the spec, section 17.2:
An expression E is an attribute-argument-expression if all of the following statements are true:
The type of E is an attribute parameter type (ยง17.1.3).
At compile-time, the value of E can be resolved to one of the following:
A constant value.
A System.Type object.
A one-dimensional array of attribute-argument-expressions.
Here's an example:
using System;
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
public class SampleAttribute : Attribute
{
public SampleAttribute(int[] foo)
{
}
}
[Sample(new int[]{1, 3, 5})]
class Test
{
}
Yes, but you need to initialize the array that you are passing in. Here is an example from a row test in our unit tests that tests a variable number of command line options;
[Row( new[] { "-l", "/port:13102", "-lfsw" } )]
public void MyTest( string[] args ) { //... }
You can do that. Another example could be:
class MyAttribute: Attribute
{
public MyAttribute(params object[] args)
{
}
}
[MyAttribute("hello", 2, 3.14f)]
class Program
{
static void Main(string[] args)
{
}
}
To piggy back on Marc Gravell's answer, yes you can define an attribute with array parameters but applying an attribute with an array parameter is not CLS-compliant. However just defining an attribute with an array property is perfectly CLS-compliant.
What made me realize this was that Json.NET, a CLS-compliant library, has an attribute class JsonPropertyAttribute with a property named ItemConverterParameters that's an array of objects.
I use maybe a bit stupid workaround using this trick:
public class CLParam : Attribute
{
/// <summary>
/// Command line parameter
/// </summary>
public string Names { get; set; }
}
and then splitting the Names into string[]:
var names = loadAtt.Names.Split(',');
I allows me to use attribute like this:
class CLContext
{
[CLParam(Names = "selectscene,ss")]
public List<string> SelectScene { get; set; }
But of course for ints you would need to parse texts, so maybe a bit slow...

Categories

Resources