关于Correlated subquery用于From(join)的情况

这里是定义,但有问题的主要是用于from(join)的时候,实际用下来,T-Sql是支持的(Sybase有条件支持),而P/L sql似乎不支持(据说oracle 10支持,但是个bug),StackOverflow有人讨论,还有这个连接也是。

而MySql,现在属于Oracle,也官方说明不支持。

Subqueries in the FROM clause cannot be correlated subqueries. They are materialized (executed to produce a result set) before evaluating the outer query, so they cannot be evaluated per row of the outer query.

wpf中重用style和template的经验

近日需要在两个有继承关系的UserControl上实现类似的style,要命的是这style里还带有事件处理的c#代码。定义重复的style和c#代码是不可接受的。第一个想法是把相同的style和c#代码放在基类Control的xaml和class里,但是由于子类也要有自己的特定的xaml,visualStudio提示xaml里对应的class的基类不能是一个已经用xaml定义过的类。这一点要求太没有道理了,xaml就不能基类+子类混合一下吗?

没办法,只能让这两个有继承关系的Control都继承自一个没有定义过xaml的更上层的Control,然后他们两者自己有各自的xaml,但是,难道一些公共style不能用一个文件里的吗?当然可以,用这样的xaml就可以不但把style的xaml,也把style的c# code都包含进来了。

<local:ConfiguredDataGrid.Resources>
       <ResourceDictionary>
           <ResourceDictionary.MergedDictionaries>
               <ResourceDictionary Source="../Resources/FilterStyle.xaml" />

如果用c#来写,就是类似

_resources = Application.LoadComponent(
                           new Uri(
                               "/xxxx.ClientUI;component/Resources/generic.xaml",
                               UriKind.Relative)) as ResourceDictionary;

这样的写法。

这其中的FilterStyle和generic两个xaml,可以仅仅是xaml文件,里面含有若干带有x:key的template,style,供包含了这个ResourceDictionary的xaml使用。但我需要带自己的c#事件处理代码,则必须有code behind的class,于是我令FilterStyle的root element就用了ResourceDictionary,而且这个ResourceDictionary带有x:Class

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="xxxx.Resources.FilterStyle" 

于是.cs里就是一个ResourceDictionary的partial子类,可以用VisualStudio生成UserControl的模版来改。只是由于这不是一个真的UserControl,也就不能调用基类的InitializeComponent(),没有IDE帮忙生成的放在obj目录里的.g.cs文件,也不需要该helper class来声明xaml里标记的components。

public partial class FilterStyle : ResourceDictionary

public FilterStyle()
        {
           // InitializeComponent();
        }

这样如果要在c#的事件处理逻辑里和xaml定义的components互动,就只能通过event handler的sender来遍历视觉树找到自己需要的东西了。

Struct 作为 Pointer Type的使用实例

来自MSDN。(更新:标题不准确,msdn指的pointer type是 “基础类型 *” 格式定义的变量类型,其中基础类型(referent type)可以是非托管类或者只包含非托管类型的自定义struct,因为pointer type不归GC管,所以不允许有reference type参与其中或者属于用户自定义struct。

参考http://books.google.com.hk/books?id=g6axWRRpJZwC&pg=PA712&lpg=PA712&dq=Any+user-defined+struct+type+that+contains+fields+of+unmanaged+types&source=bl&ots=Hy5jfiHo5K&sig=wCPiDy2c0pP4XfSkJcoMbKyHuWs&hl=zh-TW&sa=X&ei=rbwnU7ubCI-tiQezm4HwDw&ved=0CE0Q6AEwAw#v=onepage&q=Any%20user-defined%20struct%20type%20that%20contains%20fields%20of%20unmanaged%20types&f=false

下面的代码里的Node Struct就是满足条件的自定义struct,但是,另一方面,可以说是不相关的一点,我发现即使struct里含有string类型的成员和其他自定义struct, 直接试用时用reflector看到的仍然是根据地址来用的(也就是用ldloca之类的IL),也就是说它也是像pointer一样被使用的。没有用“基础类型 *“的格式就会被直接当作pointer type来用。从这个角度来说,标题又是对的。但是,这种情况下如果struct里含有string的reference,那个string能被GC吗?待验证。更新:string是immutable的特殊类,用weakReference.Alive来判断的话,GC.Collect()不会影响到它。用自己的类做实验,结果是可以被GC掉的。而这种含有managed成员的struct,就无法再用“基础类型 *“的格式来取得它的地址,它已经是作为managed Type的struct,:

Error 2 Cannot take the address of, get the size of, or declare a pointer to a managed type XXXXXX

所以,这种情况下的struct其实也不算可以作为point type。

这可真是c#和c++的一个大不同,这也解决了为什么用reflector看下列的代码(pointer和address操作必须用unsafe)

public   struct Node
   {
       public int Data;
   }
   class TestPointer
   {
       public unsafe Node* getNode(int i)
       {
           Node n = new Node();
           n.Data = i;
           Node* ptr = &n;
           return ptr;
       }

 

会生成c#版本的

[StructLayout(LayoutKind.Sequential)]
public struct Node
{
    public int Data;
}

public unsafe Node* getNode(int i)
{
    Node n;
    Node* ptr;
    Node* CS$1$0000;
    n = new Node();
    &n.Data = i;
    ptr = (IntPtr) &n;
    CS$1$0000 = ptr;
Label_0019:
    return CS$1$0000;
}

在n.Data = i;这句上,生成出的C#代码实际上是加了&(取地址)符号的。而如果你想在源代码里使用&n.Data=i,却不可以编译通过。所以,编译器在你访问struct的成员的时候会帮你标记出这是个指针访问(为什么不是变成n->Data呢,据说是reflector的C#语言反编译的语法bug?)看IL版本,实际还是指针访问

.method public hidebysig instance valuetype TestPointerForStruct.Node* getNode(int32 i) cil managed
{
    .maxstack 2
    .locals init (
        [0] valuetype TestPointerForStruct.Node n,
        [1] valuetype TestPointerForStruct.Node* ptr,
        [2] valuetype TestPointerForStruct.Node* CS$1$0000)
    L_0000: nop
    L_0001: ldloca.s n
    L_0003: initobj TestPointerForStruct.Node
    L_0009: ldloca.s n //把变量n的地址压栈
    L_000b: ldarg.1  //把第一个参数,也就是i,压栈
    L_000c: stfld int32 TestPointerForStruct.Node::Data  //成员赋值
    L_0011: ldloca.s n
    L_0013: conv.u
    L_0014: stloc.1
    L_0015: ldloc.1
    L_0016: stloc.2
    L_0017: br.s L_0019
    L_0019: ldloc.2
    L_001a: ret
}

 

对比类的赋值源代码:

  m = new Myclass();
   m.Name = “23”;

生成的IL是:
L_003a: newobj instance void TestPointerForStruct.Myclass::.ctor()
   L_003f: stloc.3
   L_0040: ldloc.3  //把第三个变量,这里也就是m,压栈
   L_0041: ldstr “23” //常量压栈
   L_0046: stfld string TestPointerForStruct.Myclass::Name 。//成员赋值

所以指针类型(值类型)和引用类型的成员访问(偏移访问)都是一样的IL,只是压栈的时候一个是用ldloca.s var,压的是var的地址,另一个直接压第x个变量ldloc.x

注:上面两段IL的主要区别就是ldloc和ldloca的区别,也就是一个a,address的区别。