C # and general casting parameter

I come from C ++ template programming and sometimes get very confused with generics. Since there is no specialization, I tried to use casting. Here is what I have:

public interface INonGen
{
    void Get<T>(ref T value);
}

public interface IGen<U> : INonGen
{

}

public class Gen<U> : IGen<U>
{
    private U u;
    public void Get<T>(ref T value)
    {
        if (value is U)
        {
            value = (T) u;
        }         
        else
            throw new Exception();
    }
}

This does not compile.

I can do it?

The reason I want this: with C ++ templates, I would do specializations for supported types and a non-specialized version that throws an exception.

The basic idea is this: not a common interface that has a common method. Trying to get the value using the correct type should work; trying to use the wrong type can throw.

We must maintain type safety, so I need to return the instance / value of the correct type. Any shortcuts above the object are unacceptable, and none of them restricts the type in a nonequivalent interface.

, . ( ), , ( , T); - , T; .

+4
4

, , . , as, , InvalidCastException, null, . as, .

public class Gen<U> : IGen<U>
{
    private U u;
    public void Get<T>(ref T value)
            where T : class
    {
        if (value is U)
        {
            value = u as T;
        }         
        else
            throw new Exception();
    }
}

, Object:

value = (T)(object)u;

. value is U, , u is T? :

 var gen = new Gen<Base>();
 gen.Set(new DerivedA()); // sets u;
 var b = new DerivedB();
 gen.Get(ref b);

value is Base, u is DerivedB. .

, :

public interface INonGen
{
    object Value { get; }
}

public interface IGen<U> : INonGen
{
}

public class Gen<U> : IGen<U>
{
    private U u;
    public object Value
    {
       get { return u; }
    }
}

:

double value = (double)dictionary[key].Value;

An InvalidCastException , . , ?

+3

, INonGen , , . , . - ; o)

public interface IGen<T>
{
    void Get(ref T value);
}

public class Gen<T, U> : IGen<T> where U : T
{
    private U u;

    public void Get(ref T value) 
    {
        if (value is U)
        {
            value = (T)u;
        }
        else
            throw new Exception();
    }
}

, generic type , U : T . . U T, .

as, , , null, , . .

INonGen , generic , - .

public interface INonGen
{
    void NonGenericMethod();
    void GenericMethod<V>(V parameter);
}

public interface IGen<T> : INonGen
{
    void Get(ref T value);
}

public class Gen<T, U> : IGen<T> where U : T
{
    private U u;

    public void Get(ref T value) 
    {
        if (value is U)
        {
            value = (T)u;
        }
        else
            throw new Exception();
    }

    public void NonGenericMethod()
    {
    }

    public void GenericMethod<V>(V parameter)
    {
    }
}
+1

...

public class Gen<U> : IGen<U> where U : T
{
    private U u;
    public void Get<T>(ref T value)
    {
        if (value is U)
        {
            value = (T) u;
        }         
        else
            throw new Exception();
    }
}

, U , T.

0

-, ref . .

public interface IThing
{
    object Value { get; }
}

public interface IThing<T> : IThing
{
    T Value { get; }
}

public class Thing<T> : IThing<T>
{
    private T t;

    public object Value
    {
        get
        {
            return this.Get();
        }
    }

    public T Value<T>()
    {
        get
        {
            return this.t;
        }
    }
}

- ,

public interface ICrazyThing<T>
{
    void Get<T>(ref T crazy);
}

public class CrazyThing<U, T> : IThing<T> where T : U
{
    private U u;

    public void Get<T>(ref T crazy)
    {
       crazy = this.u;   
    }
}

Even in a crazy world, it outwould be a better choice than ref, because the value passed in is a meaningless instance that has nothing to do with the result.

0
source

All Articles